server: Define interactivity sooner

Change when the server discovers if the install is interactive or not.
This allows clients to display autoinstall errors in an interactive
way, if applicable. This also enables accessing the ssh_info endpoint
before all of the controllers are loaded. Autoinstall loading happens
after the loading cloudinit stage, so this should be accessible by then.
If a failure happens during/before cloudinit is finished, `interactive`
will still be set to `None` and clients should default to the
non-interactive case.
This commit is contained in:
Chris Peterson 2024-03-04 11:52:53 -08:00
parent 32e7dc54c5
commit 30dfc2f0cb
3 changed files with 29 additions and 12 deletions

View File

@ -333,14 +333,17 @@ class SubiquityClient(TuiApplication):
print(line)
return
# Get the variant from the server and reload desired
# controllers if an override exists
variant = await self.client.meta.client_variant.GET()
if variant != self.variant:
self.variant = variant
controllers = self.variant_to_controllers.get(variant)
if controllers:
self.load_controllers(controllers)
# The server could end up in an error state before we get here
# so skip to allow urwid to come up and show an error screen
if status.state != ApplicationState.ERROR:
# Get the variant from the server and reload desired
# controllers if an override exists
variant = await self.client.meta.client_variant.GET()
if variant != self.variant:
self.variant = variant
controllers = self.variant_to_controllers.get(variant)
if controllers:
self.load_controllers(controllers)
await super().start()
# Progress uses systemd to collect and display the installation

View File

@ -125,6 +125,7 @@ class API:
"""Restart the server process."""
class ssh_info:
@allowed_before_start
def GET() -> Optional[LiveSessionSSHInfo]:
...

View File

@ -511,10 +511,27 @@ class SubiquityServer(Application):
only_early,
self.autoinstall,
)
# Set the interactivity as early as possible so autoinstall validation
# errors can be shown to the user in an interactive way, if applicable.
#
# In the case of no autoinstall data, we set interactive=true.
#
# Otherwise, we need to check the interactivity of the session on both
# calls (early=True and early=False) because it's possible that an
# early command mutates the autoinstall and changes the value of
# interactive-sections.
if not self.autoinstall:
self.interactive = True
return
with open(self.autoinstall) as fp:
self.autoinstall_config = yaml.safe_load(fp)
# Check every time
self.interactive = bool(self.autoinstall_config.get("interactive-sections"))
if only_early:
self.controllers.Reporting.setup_autoinstall()
self.controllers.Reporting.start()
@ -714,10 +731,6 @@ class SubiquityServer(Application):
open(stamp_file, "w").close()
await asyncio.sleep(1)
self.load_autoinstall_config(only_early=False)
if self.autoinstall_config:
self.interactive = bool(self.autoinstall_config.get("interactive-sections"))
else:
self.interactive = True
if not self.interactive and not self.opts.dry_run:
open("/run/casper-no-prompt", "w").close()
self.load_serialized_state()