Merge pull request #1266 from ogayot/FR-2237

Fix storage screen sometimes not refreshing after slow probing
This commit is contained in:
Olivier Gayot 2022-04-22 10:52:37 +02:00 committed by GitHub
commit 3f07ca1b1b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 45 additions and 13 deletions

View File

@ -21,7 +21,7 @@ import os
import signal import signal
import sys import sys
import traceback import traceback
from typing import Dict, List, Optional from typing import Callable, Dict, List, Optional, Union
import aiohttp import aiohttp
@ -486,11 +486,20 @@ class SubiquityClient(TuiApplication):
log.debug("showing InstallConfirmation over %s", self.ui.body) log.debug("showing InstallConfirmation over %s", self.ui.body)
self.add_global_overlay(InstallConfirmation(self)) self.add_global_overlay(InstallConfirmation(self))
async def _start_answers_for_view(self, controller, view): async def _start_answers_for_view(
self, controller, view: Union[BaseView, Callable[[], BaseView]]):
def noop():
return view
if callable(view):
deref_view = view
else:
deref_view = noop
# The view returned by make_view_for_controller is not always shown # The view returned by make_view_for_controller is not always shown
# immediately (if progress is being shown, but has not yet been shown # immediately (if progress is being shown, but has not yet been shown
# for a full second) so wait until it is before starting the answers. # for a full second) so wait until it is before starting the answers.
while self.ui.body is not view: while self.ui.body is not deref_view():
await asyncio.sleep(0.1) await asyncio.sleep(0.1)
coro = controller.run_answers() coro = controller.run_answers()
if inspect.iscoroutine(coro): if inspect.iscoroutine(coro):

View File

@ -15,8 +15,10 @@
import asyncio import asyncio
import logging import logging
from typing import Callable, Optional
from subiquitycore.lsb_release import lsb_release from subiquitycore.lsb_release import lsb_release
from subiquitycore.view import BaseView
from subiquity.client.controller import SubiquityTuiController from subiquity.client.controller import SubiquityTuiController
from subiquity.common.filesystem import gaps from subiquity.common.filesystem import gaps
@ -50,19 +52,34 @@ class FilesystemController(SubiquityTuiController, FilesystemManipulator):
self.answers.setdefault('guided', False) self.answers.setdefault('guided', False)
self.answers.setdefault('guided-index', 0) self.answers.setdefault('guided-index', 0)
self.answers.setdefault('manual', []) self.answers.setdefault('manual', [])
self.current_view: Optional[BaseView] = None
async def make_ui(self) -> Callable[[], BaseView]:
def get_current_view() -> BaseView:
assert self.current_view is not None
return self.current_view
async def make_ui(self):
status = await self.endpoint.guided.GET() status = await self.endpoint.guided.GET()
if status.status == ProbeStatus.PROBING: if status.status == ProbeStatus.PROBING:
self.app.aio_loop.create_task(self._wait_for_probing()) self.app.aio_loop.create_task(self._wait_for_probing())
return SlowProbing(self) self.current_view = SlowProbing(self)
else: else:
return self.make_guided_ui(status) self.current_view = self.make_guided_ui(status)
# NOTE: If we return a BaseView instance directly here, we have no
# guarantee that it will be displayed on the screen by the time the
# probing operation finishes. Therefore, to allow us to reliably
# replace the screen by the "Guided Storage" when the probing operation
# finishes, we add a level of indirection.
# In essence, this allows us to make modifications to the screen
# that eventually will be displayed.
# This is mostly a workaround for the issue described in LP #1968161
return get_current_view
async def _wait_for_probing(self): async def _wait_for_probing(self):
status = await self.endpoint.guided.GET(wait=True) status = await self.endpoint.guided.GET(wait=True)
self.current_view = self.make_guided_ui(status)
if isinstance(self.ui.body, SlowProbing): if isinstance(self.ui.body, SlowProbing):
self.ui.set_body(self.make_guided_ui(status)) self.ui.set_body(self.current_view)
else: else:
log.debug("not refreshing the display. Current display is %r", log.debug("not refreshing the display. Current display is %r",
self.ui.body) self.ui.body)

View File

@ -18,6 +18,7 @@ import inspect
import logging import logging
import os import os
import signal import signal
from typing import Callable, Optional, Union
import urwid import urwid
@ -34,6 +35,7 @@ from subiquitycore.tuicontroller import Skip
from subiquitycore.ui.utils import LoadingDialog from subiquitycore.ui.utils import LoadingDialog
from subiquitycore.ui.frame import SubiquityCoreUI from subiquitycore.ui.frame import SubiquityCoreUI
from subiquitycore.utils import astart_command from subiquitycore.utils import astart_command
from subiquitycore.view import BaseView
log = logging.getLogger('subiquitycore.tui') log = logging.getLogger('subiquitycore.tui')
@ -122,7 +124,8 @@ class TuiApplication(Application):
before_hook() before_hook()
schedule_task(_run()) schedule_task(_run())
async def make_view_for_controller(self, new): async def make_view_for_controller(self, new) \
-> Union[BaseView, Callable[[], BaseView]]:
new.context.enter("starting UI") new.context.enter("starting UI")
if self.opts.screens and new.name not in self.opts.screens: if self.opts.screens and new.name not in self.opts.screens:
raise Skip raise Skip
@ -205,7 +208,8 @@ class TuiApplication(Application):
async def wait_with_progress(self, awaitable): async def wait_with_progress(self, awaitable):
return await self._wait_with_indication(awaitable, self.show_progress) return await self._wait_with_indication(awaitable, self.show_progress)
async def _move_screen(self, increment, coro): async def _move_screen(self, increment, coro) \
-> Optional[Union[BaseView, Callable[[], BaseView]]]:
if coro is not None: if coro is not None:
await coro await coro
old, self.cur_screen = self.cur_screen, None old, self.cur_screen = self.cur_screen, None
@ -230,13 +234,15 @@ class TuiApplication(Application):
except Exception: except Exception:
self.controllers.index = cur_index self.controllers.index = cur_index
raise raise
else:
return
async def move_screen(self, increment, coro): async def move_screen(self, increment, coro):
view = await self.wait_with_progress( view_or_callable = await self.wait_with_progress(
self._move_screen(increment, coro)) self._move_screen(increment, coro))
if view is not None: if view_or_callable is not None:
if callable(view_or_callable):
view = view_or_callable()
else:
view = view_or_callable
self.ui.set_body(view) self.ui.set_body(view)
def next_screen(self, coro=None): def next_screen(self, coro=None):