Merge pull request #661 from mwhudson/autoinstall-confirmation

be a bit less cavalier about running the install in autoinstall mode
This commit is contained in:
Dimitri John Ledkov 2020-04-01 22:11:33 +01:00 committed by GitHub
commit 5126417397
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 105 additions and 44 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

@ -71,6 +71,9 @@ def parse_options(argv):
help='Synthesize a click on a button matching PAT')
parser.add_argument('--answers')
parser.add_argument('--autoinstall', action='store')
with open('/proc/cmdline') as fp:
cmdline = fp.read()
parser.add_argument('--kernel-cmdline', action='store', default=cmdline)
parser.add_argument('--source', default=[], action='append',
dest='sources', metavar='URL',
help='install from url instead of default.')

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

@ -148,10 +148,8 @@ class RefreshController(SubiquityController):
"""Return the channel we should refresh subiquity to."""
if 'channel' in self.answers:
return self.answers['channel']
with open('/proc/cmdline') as fp:
cmdline = fp.read()
prefix = "subiquity-channel="
for arg in cmdline.split():
for arg in self.app.kernel_cmdline:
if arg.startswith(prefix):
log.debug(
"get_refresh_channel: found %s on kernel cmdline", arg)

View File

@ -16,6 +16,7 @@
import logging
import os
import platform
import shlex
import signal
import sys
import traceback
@ -119,6 +120,7 @@ class Subiquity(Application):
super().__init__(opts)
self.block_log_dir = block_log_dir
self.kernel_cmdline = shlex.split(opts.kernel_cmdline)
if opts.snaps_from_examples:
connection = FakeSnapdConnection(
os.path.join(
@ -139,6 +141,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 +230,40 @@ 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:
if self.interactive():
from subiquity.ui.views.installprogress import (
InstallConfirmation,
)
self.ui.body.show_stretchy_overlay(
InstallConfirmation(self.ui.body, self))
else:
yes = _('yes')
no = _('no')
answer = no
if 'autoinstall' in self.kernel_cmdline:
answer = yes
else:
print(_("Confirmation is required to continue."))
print(_("Add 'autoinstall' to your kernel command line to"
" avoid this"))
print()
prompt = "\n\n{} ({}|{})".format(
_("Continue with autoinstall?"), yes, no)
while answer != yes:
print(prompt)
answer = input()
self.confirm_install()
super().next_screen()
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()