decouple install confirmation from filesystem view

because, in a partially interactive install, we might not show the
filesystem view at all, but should still ask for confirmation before
starting curtin
This commit is contained in:
Michael Hudson-Doyle 2020-03-30 12:17:30 +13:00
parent 91a79037a9
commit abc8f1dfb2
6 changed files with 80 additions and 41 deletions

View File

@ -1,8 +1,22 @@
version: 1
early-commands:
- echo a
- sleep 1
- echo a
late-commands:
- echo a
- sleep 1
- echo a
keyboard:
layout: gb
interactive-sections:
- keyboard
- snaps
- identity
snaps:
- name: etcd
channel: 3.2/stable
identity:
realname: ''
username: ubuntu
password: '$6$wdAcoXrU039hKYPd$508Qvbe7ObUnxoj15DRCkzC3qO7edjH0VV7BPNRDYK4QR8ofJaEEF2heacn0QgD.f8pO8SNp83XNdWG6tocBM1'
hostname: ubuntu

View File

@ -341,6 +341,7 @@ class FilesystemController(SubiquityController):
elif action['action'] == 'done':
if not self.ui.body.done.enabled:
raise Exception("answers did not provide complete fs config")
self.app.confirm_install()
self.finish()
else:
raise Exception("could not process action {}".format(action))
@ -348,6 +349,7 @@ class FilesystemController(SubiquityController):
def manual(self):
self.ui.set_body(FilesystemView(self.model, self))
if self.answers['guided']:
self.app.confirm_install()
self.finish()
if self.answers['manual']:
self._run_iterator(self._run_actions(self.answers['manual']))

View File

@ -112,6 +112,7 @@ class InstallProgressController(SubiquityController):
self._log_syslog_identifier = 'curtin_log.%s' % (os.getpid(),)
self.tb_extractor = TracebackExtractor()
self.curtin_context = None
self.confirmation = asyncio.Event()
def interactive(self):
return self.app.interactive()
@ -281,6 +282,8 @@ class InstallProgressController(SubiquityController):
await asyncio.wait(
{e.wait() for e in self.model.install_events})
await self.confirmation.wait()
await self.curtin_install(context)
await asyncio.wait(

View File

@ -139,6 +139,7 @@ class Subiquity(Application):
self.note_data_for_apport("SnapUpdated", str(self.updated))
self.note_data_for_apport("UsingAnswers", str(bool(self.answers)))
self.install_confirmed = False
self.reboot_on_exit = False
def exit(self):
@ -227,6 +228,21 @@ class Subiquity(Application):
if Reporting is not None:
Reporting.report_finish_event(name, description, status, level)
def confirm_install(self):
self.install_confirmed = True
self.controllers.InstallProgress.confirmation.set()
def next_screen(self):
can_install = all(e.is_set() for e in self.base_model.install_events)
if can_install and not self.install_confirmed:
from subiquity.ui.views.installprogress import (
InstallConfirmation,
)
self.ui.body.show_stretchy_overlay(
InstallConfirmation(self.ui.body, self))
else:
super().next_screen()
def interactive(self):
if not self.autoinstall_config:
return True

View File

@ -35,8 +35,6 @@ from subiquitycore.ui.actionmenu import (
)
from subiquitycore.ui.buttons import (
back_btn,
cancel_btn,
danger_btn,
done_btn,
menu_btn,
other_btn,
@ -77,40 +75,6 @@ from .raid import RaidStretchy
log = logging.getLogger('subiquity.ui.filesystem.filesystem')
confirmation_text = _("""\
Selecting Continue below will begin the installation process and \
result in the loss of data on the disks selected to be formatted.
You will not be able to return to this or a previous screen once \
the installation has started.
Are you sure you want to continue?""")
class FilesystemConfirmation(Stretchy):
def __init__(self, parent, controller):
self.parent = parent
self.controller = controller
widgets = [
Text(_(confirmation_text)),
Text(""),
button_pile([
cancel_btn(_("No"), on_press=self.cancel),
danger_btn(_("Continue"), on_press=self.ok)]),
]
super().__init__(
_("Confirm destructive action"),
widgets,
stretchy_index=0,
focus_index=2)
def ok(self, sender):
self.controller.finish()
def cancel(self, sender):
self.parent.remove_overlay()
@attr.s
class MountInfo:
mount = attr.ib(default=None)
@ -557,5 +521,4 @@ class FilesystemView(BaseView):
self.controller.reset()
def done(self, button):
self.show_stretchy_overlay(FilesystemConfirmation(self,
self.controller))
self.controller.finish()

View File

@ -20,11 +20,17 @@ from urwid import (
)
from subiquitycore.view import BaseView
from subiquitycore.ui.buttons import cancel_btn, ok_btn, other_btn
from subiquitycore.ui.buttons import (
cancel_btn,
danger_btn,
ok_btn,
other_btn,
)
from subiquitycore.ui.container import Columns, ListBox, Pile
from subiquitycore.ui.form import Toggleable
from subiquitycore.ui.spinner import Spinner
from subiquitycore.ui.utils import button_pile, Padding
from subiquitycore.ui.utils import button_pile, Padding, rewrap
from subiquitycore.ui.stretchy import Stretchy
from subiquitycore.ui.width import widget_width
log = logging.getLogger("subiquity.views.installprogress")
@ -146,3 +152,38 @@ class ProgressView(BaseView):
def close_log(self, btn):
self._w = self.event_pile
confirmation_text = _("""\
Selecting Continue below will begin the installation process and
result in the loss of data on the disks selected to be formatted.
You will not be able to return to this or a previous screen once
the installation has started.
Are you sure you want to continue?""")
class InstallConfirmation(Stretchy):
def __init__(self, parent, app):
self.parent = parent
self.app = app
widgets = [
Text(rewrap(_(confirmation_text))),
Text(""),
button_pile([
cancel_btn(_("No"), on_press=self.cancel),
danger_btn(_("Continue"), on_press=self.ok)]),
]
super().__init__(
_("Confirm destructive action"),
widgets,
stretchy_index=0,
focus_index=2)
def ok(self, sender):
self.app.confirm_install()
self.app.next_screen()
def cancel(self, sender):
self.parent.remove_overlay()