only wait 10 minutes for cloud-init status --wait to complete, not forever

and show a message to the user when this happens
This commit is contained in:
Michael Hudson-Doyle 2020-12-08 21:43:38 +13:00
parent bbcf050205
commit 32dbf28767
5 changed files with 51 additions and 3 deletions

View File

@ -54,6 +54,9 @@ from subiquity.ui.views.help import HelpMenu
from subiquity.ui.views.installprogress import (
InstallConfirmation,
)
from subiquity.ui.views.welcome import (
CloudInitFail,
)
log = logging.getLogger('subiquity.client.client')
@ -273,6 +276,8 @@ class SubiquityClient(TuiApplication):
self.aio_loop,
[status.log_syslog_id],
self.controllers.Progress.log_line)
if not status.cloud_init_ok:
self.add_global_overlay(CloudInitFail(self))
self.error_reporter.load_reports()
for report in self.error_reporter.reports:
if report.kind == ErrorReportKind.UI and not report.seen:

View File

@ -16,6 +16,7 @@
import argparse
import logging
import os
import subprocess
import sys
import time
@ -108,9 +109,15 @@ def main():
logger.info("Starting Subiquity server revision {}".format(version))
logger.info("Arguments passed: {}".format(sys.argv))
cloud_init_ok = True
if not opts.dry_run:
ci_start = time.time()
status_txt = run_command(["cloud-init", "status", "--wait"]).stdout
try:
status_txt = run_command(
["cloud-init", "status", "--wait"], timeout=600).stdout
except subprocess.TimeoutExpired:
status_txt = '<timeout>'
cloud_init_ok = False
logger.debug("waited %ss for cloud-init", time.time() - ci_start)
if "status: done" in status_txt:
logger.debug("loading cloud config")
@ -133,7 +140,7 @@ def main():
"cloud-init status: %r, assumed disabled",
status_txt)
server = SubiquityServer(opts, block_log_dir)
server = SubiquityServer(opts, block_log_dir, cloud_init_ok)
server.note_file_for_apport(
"InstallerServerLog", logfiles['debug'])

View File

@ -35,6 +35,7 @@ class ApplicationState(enum.Enum):
@attr.s(auto_attribs=True)
class ApplicationStatus:
state: ApplicationState
cloud_init_ok: bool
early_commands_syslog_id: str
log_syslog_id: str
event_syslog_id: str

View File

@ -74,6 +74,7 @@ class MetaController:
await self.app.state_event.wait()
return ApplicationStatus(
self.app.state,
cloud_init_ok=self.app.cloud_init_ok,
early_commands_syslog_id=self.app.early_commands_syslog_id,
event_syslog_id=self.app.event_syslog_id,
log_syslog_id=self.app.log_syslog_id)
@ -140,9 +141,10 @@ class SubiquityServer(Application):
root = os.path.abspath('.subiquity')
return SubiquityModel(root, self.opts.sources)
def __init__(self, opts, block_log_dir):
def __init__(self, opts, block_log_dir, cloud_init_ok):
super().__init__(opts)
self.block_log_dir = block_log_dir
self.cloud_init_ok = cloud_init_ok
self._state = ApplicationState.STARTING
self.state_event = asyncio.Event()
self.confirming_tty = ''

View File

@ -25,6 +25,7 @@ from urwid import Text
from subiquitycore.ui.buttons import forward_btn, other_btn
from subiquitycore.ui.container import ListBox
from subiquitycore.ui.stretchy import Stretchy
from subiquitycore.ui.utils import button_pile, rewrap, screen
from subiquitycore.screen import is_linux_tty
from subiquitycore.view import BaseView
@ -58,6 +59,13 @@ You can also connect to the installer over the network via SSH, which
will allow use of rich mode.
"""
CLOUD_INIT_FAIL_TEXT = """
cloud-init failed to complete after 10 minutes of waiting. This
suggests a bug, which we would appreciate help understanding. If you
could file a bug at https://bugs.launchpad.net/subiquity/+filebug and
attach the contents of /var/log, it would be most appreciated.
"""
def get_languages():
base = os.environ.get("SNAP", ".")
@ -157,3 +165,28 @@ class WelcomeView(BaseView):
def local_help(self):
return _("Help choosing a language"), _(HELP)
class CloudInitFail(Stretchy):
def __init__(self, app):
self.app = app
self.shell_btn = other_btn(
_("Switch to a shell"), on_press=self._debug_shell)
self.close_btn = other_btn(
_("Close"), on_press=self._close)
widgets = [
Text(rewrap(_(CLOUD_INIT_FAIL_TEXT))),
Text(''),
button_pile([self.shell_btn, self.close_btn]),
]
super().__init__(
"",
widgets,
stretchy_index=0,
focus_index=2)
def _debug_shell(self, sender):
self.app.debug_shell()
def _close(self, sender):
self.app.remove_global_overlay(self)