Merge pull request #841 from mwhudson/skip-confirm

handling skipping controllers and confirmation in client/server comms
This commit is contained in:
Michael Hudson-Doyle 2020-09-23 16:07:48 +12:00 committed by GitHub
commit 8dc97707fe
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 60 additions and 12 deletions

View File

@ -92,7 +92,6 @@ class InstallProgressController(SubiquityTuiController):
self._log_syslog_identifier = 'curtin_log.%s' % (os.getpid(),)
self.tb_extractor = TracebackExtractor()
self.curtin_event_contexts = {}
self.confirmation = asyncio.Event()
def interactive(self):
return self.app.interactive()
@ -307,7 +306,7 @@ class InstallProgressController(SubiquityTuiController):
self.update_state(InstallState.NEEDS_CONFIRMATION)
await self.confirmation.wait()
await self.model.confirmation.wait()
self.update_state(InstallState.RUNNING)

View File

@ -191,8 +191,6 @@ class Subiquity(TuiApplication):
self.note_data_for_apport("SnapUpdated", str(self.updated))
self.note_data_for_apport("UsingAnswers", str(bool(self.answers)))
self.install_confirmed = False
def subiquity_event(self, event):
if event["MESSAGE"] == "starting install":
if event["_PID"] == os.getpid():
@ -320,6 +318,11 @@ class Subiquity(TuiApplication):
self.server_updated = headers['x-updated']
elif self.server_updated != headers['x-updated']:
self.restart(remove_last_screen=False)
status = response.headers.get('x-status')
if status == 'skip':
raise Skip
elif status == 'confirm':
raise Confirm
if headers.get('x-error-report') is not None:
ref = from_json(ErrorReportRef, headers['x-error-report'])
raise Abort(ref)
@ -405,8 +408,7 @@ class Subiquity(TuiApplication):
listener.report_finish_event(context, description, status)
async def confirm_install(self):
self.install_confirmed = True
self.controllers.InstallProgress.confirmation.set()
self.base_model.confirm()
def _cancel_show_progress(self):
if self.show_progress_handle is not None:
@ -466,11 +468,8 @@ class Subiquity(TuiApplication):
self.next_screen(self.confirm_install())
async def make_view_for_controller(self, new):
can_install = all(e.is_set() for e in self.base_model.install_events)
if can_install and not self.install_confirmed:
if new.model_name:
if not self.base_model.is_configured(new.model_name):
raise Confirm
if self.base_model.needs_confirmation(new.model_name):
raise Confirm
if new.interactive():
view = await super().make_view_for_controller(new)
if new.answers:

View File

@ -119,6 +119,8 @@ class SubiquityModel:
self.ssh = SSHModel()
self.userdata = {}
self.confirmation = asyncio.Event()
self._events = {
name: asyncio.Event() for name in ALL_MODEL_NAMES
}
@ -143,6 +145,16 @@ class SubiquityModel:
}
log.debug("model %s is configured, to go %s", model_name, unconfigured)
def needs_confirmation(self, model_name):
if model_name is None:
return False
if not all(e.is_set() for e in self.install_events):
return None
return not self.confirmation.is_set()
def confirm(self):
self.confirmation.set()
def is_configured(self, model_name):
return self._events[model_name].is_set()

View File

@ -0,0 +1,26 @@
# Copyright 2020 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 <http://www.gnu.org/licenses/>.
import logging
from subiquitycore.controller import (
BaseController,
)
log = logging.getLogger("subiquity.server.controller")
class SubiquityController(BaseController):
pass

View File

@ -21,7 +21,10 @@ from aiohttp import web
from subiquitycore.core import Application
from subiquity.common.api.server import bind
from subiquity.common.api.server import (
bind,
controller_for_request,
)
from subiquity.common.apidef import API
from subiquity.common.errorreport import (
ErrorReportKind,
@ -32,6 +35,7 @@ from subiquity.common.types import (
ApplicationState,
ErrorReportRef,
)
from subiquity.server.controller import SubiquityController
from subiquity.server.errors import ErrorController
@ -83,6 +87,14 @@ class SubiquityServer(Application):
updated = 'yes'
else:
updated = 'no'
controller = await controller_for_request(request)
if isinstance(controller, SubiquityController):
if not controller.interactive():
return web.Response(
headers={'x-status': 'skip', 'x-updated': updated})
elif self.base_model.needs_confirmation(controller.model_name):
return web.Response(
headers={'x-status': 'confirm', 'x-updated': updated})
resp = await handler(request)
resp.headers['x-updated'] = updated
if resp.get('exception'):