allow app state transition from NEEDS_CONFIRMATION to WAITING

consider the following scenario, admittedly one that is not possible
today:

 * There is an "install model" that is required for server and not
   desktop (let's say "mirror")
 * The user initially selects a desktop install and moves through the
   screens until they are asked for confirmation.
 * At this point the user moves back through the screens and selects a
   server variant.  Now the application state of NEEDS_CONFIRMATION is
   misleading; the state needs to move back to WAITING until the mirror
   model is configured.

This is all probably excessively general but I feel like the core
control flow of the installer needs to be able to handle this sort of
thing...
This commit is contained in:
Michael Hudson-Doyle 2021-08-05 14:20:14 +12:00
parent 9080a56804
commit a5ae411c55
2 changed files with 30 additions and 8 deletions

View File

@ -121,6 +121,7 @@ class SubiquityModel:
self.userdata = {}
self._confirmation = asyncio.Event()
self._confirmation_task = None
self._configured_names = set()
self._install_model_names = install_model_names
@ -136,6 +137,15 @@ class SubiquityModel:
self._install_model_names.for_variant(variant)
self._cur_postinstall_model_names = \
self._postinstall_model_names.for_variant(variant)
unconfigured_install_model_names = \
self._cur_install_model_names - self._configured_names
if unconfigured_install_model_names:
if self._install_event.is_set():
self._install_event = asyncio.Event()
if self._confirmation_task is not None:
self._confirmation_task.cancel()
else:
self._install_event.set()
def configured(self, model_name):
self._configured_names.add(model_name)
@ -163,7 +173,17 @@ class SubiquityModel:
await self._postinstall_event.wait()
async def wait_confirmation(self):
await self._confirmation.wait()
if self._confirmation_task is None:
self._confirmation_task = asyncio.get_event_loop().create_task(
self._confirmation.wait())
try:
await self._confirmation_task
except asyncio.CancelledError:
return False
else:
return True
finally:
self._confirmation_task = None
def is_postinstall_only(self, model_name):
return model_name in self._cur_postinstall_model_names and \

View File

@ -199,17 +199,19 @@ class InstallController(SubiquityController):
async def install(self, *, context):
context.set('is-install-context', True)
try:
self.app.update_state(ApplicationState.WAITING)
while True:
self.app.update_state(ApplicationState.WAITING)
await self.model.wait_install()
await self.model.wait_install()
if not self.app.interactive:
if 'autoinstall' in self.app.kernel_cmdline:
self.model.confirm()
if not self.app.interactive:
if 'autoinstall' in self.app.kernel_cmdline:
self.model.confirm()
self.app.update_state(ApplicationState.NEEDS_CONFIRMATION)
self.app.update_state(ApplicationState.NEEDS_CONFIRMATION)
await self.model.wait_confirmation()
if await self.model.wait_confirmation():
break
self.app.update_state(ApplicationState.RUNNING)