Example #1
0
    async def curtin_install(self, *, context):
        log.debug('curtin_install')
        self.curtin_event_contexts[''] = context

        loop = self.app.aio_loop

        fds = [
            journald_listen(loop, [self.app.log_syslog_id], self.curtin_log),
            journald_listen(loop, [self._event_syslog_id], self.curtin_event),
        ]

        curtin_cmd = self._get_curtin_command()

        log.debug('curtin install cmd: {}'.format(curtin_cmd))

        async with self.app.install_lock_file.exclusive():
            try:
                our_tty = os.ttyname(0)
            except OSError:
                # This is a gross hack for testing in travis.
                our_tty = "/dev/not a tty"
            self.app.install_lock_file.write_content(our_tty)
            journal.send("starting install", SYSLOG_IDENTIFIER="subiquity")
            try:
                cp = await arun_command(self.logged_command(curtin_cmd),
                                        check=True)
            finally:
                for fd in fds:
                    loop.remove_reader(fd)

        log.debug('curtin_install completed: %s', cp.returncode)
Example #2
0
 async def connect(self):
     print("connecting...", end='', flush=True)
     while True:
         try:
             status = await self.client.meta.status.GET()
         except aiohttp.ClientError:
             await asyncio.sleep(1)
             print(".", end='', flush=True)
         else:
             break
     print("\nconnected")
     journald_listen(self.aio_loop, [status.echo_syslog_id],
                     lambda e: print(e['MESSAGE']))
     if status.state == ApplicationState.STARTING_UP:
         status = await self.client.meta.status.GET(cur=status.state)
         await asyncio.sleep(0.5)
     return status
Example #3
0
    def __init__(self, opts, block_log_dir):
        if is_linux_tty():
            self.input_filter = KeyCodesFilter()
        else:
            self.input_filter = DummyKeycodesFilter()

        self.help_menu = HelpMenu(self)
        super().__init__(opts)

        self.event_syslog_id = 'subiquity_event.{}'.format(os.getpid())
        self.log_syslog_id = 'subiquity_log.{}'.format(os.getpid())

        self.server_updated = None
        self.restarting_server = False
        self.prober = Prober(opts.machine_config, self.debug_flags)
        journald_listen(self.aio_loop, ["subiquity"],
                        self.subiquity_event,
                        seek=True)
        self.event_listeners = []
        self.install_lock_file = Lockfile(self.state_path("installing"))
        self.global_overlays = []
        self.block_log_dir = block_log_dir
        self.kernel_cmdline = shlex.split(opts.kernel_cmdline)
        if opts.snaps_from_examples:
            connection = FakeSnapdConnection(
                os.path.join(os.path.dirname(os.path.dirname(__file__)),
                             "examples", "snaps"), self.scale_factor)
        else:
            connection = SnapdConnection(self.root, self.snapd_socket_path)
        self.snapd = AsyncSnapd(connection)
        self.signal.connect_signals([
            ('network-proxy-set', lambda: schedule_task(self._proxy_set())),
            ('network-change', self._network_change),
        ])

        self.conn = aiohttp.UnixConnector(self.opts.socket)
        self.client = make_client_for_conn(API, self.conn, self.resp_hook)

        self.autoinstall_config = {}
        self.error_reporter = ErrorReporter(
            self.context.child("ErrorReporter"), self.opts.dry_run, self.root,
            self.client)

        self.note_data_for_apport("SnapUpdated", str(self.updated))
        self.note_data_for_apport("UsingAnswers", str(bool(self.answers)))
Example #4
0
    async def connect(self):

        def p(s):
            print(s, end='', flush=True)

        async def spin(message):
            p(message + '...  ')
            while True:
                for t in ['-', '\\', '|', '/']:
                    p('\x08' + t)
                    await asyncio.sleep(0.5)

        async def spinning_wait(message, task):
            spinner = self.aio_loop.create_task(spin(message))
            try:
                return await task
            finally:
                spinner.cancel()
                p('\x08 \n')

        async def _connect():
            while True:
                try:
                    return await self.client.meta.status.GET()
                except aiohttp.ClientError:
                    await asyncio.sleep(1)

        status = await spinning_wait("connecting", _connect())
        journald_listen(
            self.aio_loop,
            [status.echo_syslog_id],
            lambda e: print(e['MESSAGE']))
        if status.state == ApplicationState.STARTING_UP:
            status = await spinning_wait(
                "starting up", self.client.meta.status.GET(cur=status.state))
        if status.state == ApplicationState.CLOUD_INIT_WAIT:
            status = await spinning_wait(
                "waiting for cloud-init",
                self.client.meta.status.GET(cur=status.state))
        if status.state == ApplicationState.EARLY_COMMANDS:
            print("running early commands")
            status = await self.client.meta.status.GET(cur=status.state)
            await asyncio.sleep(0.5)
        return status
Example #5
0
    async def curtin_install(self, *, context):
        log.debug('curtin_install')
        self.curtin_event_contexts[''] = context

        loop = self.app.aio_loop

        fds = [
            journald_listen(loop, [self.app.log_syslog_id], self.log_event),
            journald_listen(loop, [self._event_syslog_id], self.curtin_event),
        ]

        curtin_cmd = self._get_curtin_command()

        log.debug('curtin install cmd: {}'.format(curtin_cmd))

        try:
            cp = await arun_command(self.logged_command(curtin_cmd),
                                    check=True)
        finally:
            for fd in fds:
                loop.remove_reader(fd)

        log.debug('curtin_install completed: %s', cp.returncode)
Example #6
0
 async def start(self):
     status = await self.connect()
     self.interactive = status.interactive
     if self.interactive:
         if self.opts.ssh:
             from subiquity.ui.views.help import (
                 ssh_help_texts, get_installer_password)
             from subiquitycore.ssh import get_ips_standalone
             texts = ssh_help_texts(
                 get_ips_standalone(),
                 get_installer_password(self.opts.dry_run))
             for line in texts:
                 if hasattr(line, 'text'):
                     if line.text.startswith('installer@'):
                         print(' ' * 4 + line.text)
                     else:
                         print(line.text)
                 else:
                     print(line)
             return
         await super().start()
         journald_listen(
             self.aio_loop,
             [status.event_syslog_id],
             self.controllers.Progress.event)
         journald_listen(
             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:
                 self.show_error_report(report.ref())
                 break
     else:
         if self.opts.run_on_serial:
             # Thanks to the fact that we are launched with agetty's
             # --skip-login option, on serial lines we can end up starting
             # with some strange terminal settings (see the docs for
             # --skip-login in agetty(8)). For an interactive install this
             # does not matter as the settings will soon be clobbered but
             # for a non-interactive one we need to clear things up or the
             # prompting for confirmation will be confusing.
             os.system('stty sane')
         journald_listen(
             self.aio_loop,
             [status.event_syslog_id],
             self.subiquity_event_noninteractive,
             seek=True)
         self.aio_loop.create_task(
             self.noninteractive_watch_app_state(status))
Example #7
0
 async def start(self):
     status = await self.connect()
     self.interactive = status.interactive
     if self.interactive:
         if self.opts.ssh:
             ssh_info = await self.client.meta.ssh_info.GET()
             texts = ssh_help_texts(ssh_info)
             for line in texts:
                 import urwid
                 if isinstance(line, urwid.Widget):
                     line = '\n'.join([
                         line.decode('utf-8').rstrip()
                         for line in line.render((1000,)).text
                         ])
                 print(line)
             return
         await super().start()
         journald_listen(
             self.aio_loop,
             [status.event_syslog_id],
             self.controllers.Progress.event)
         journald_listen(
             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:
                 self.show_error_report(report.ref())
                 break
     else:
         if self.opts.run_on_serial:
             # Thanks to the fact that we are launched with agetty's
             # --skip-login option, on serial lines we can end up starting
             # with some strange terminal settings (see the docs for
             # --skip-login in agetty(8)). For an interactive install this
             # does not matter as the settings will soon be clobbered but
             # for a non-interactive one we need to clear things up or the
             # prompting for confirmation will be confusing.
             os.system('stty sane')
         journald_listen(
             self.aio_loop,
             [status.event_syslog_id],
             self.subiquity_event_noninteractive,
             seek=True)
         self.aio_loop.create_task(
             self.noninteractive_watch_app_state(status))
Example #8
0
 async def start(self):
     self.controllers.load_all()
     self.load_serialized_state()
     await self.connect()
     if self.opts.autoinstall is not None:
         await self.load_autoinstall_config()
         if not self.interactive() and not self.opts.dry_run:
             open('/run/casper-no-prompt', 'w').close()
     interactive = self.interactive()
     if interactive:
         journald_listen(self.aio_loop, [self.event_syslog_id],
                         self.controllers.InstallProgress.event)
         journald_listen(self.aio_loop, [self.log_syslog_id],
                         self.controllers.InstallProgress.log_line)
     else:
         journald_listen(self.aio_loop, [self.event_syslog_id],
                         self.subiquity_event_noninteractive,
                         seek=True)
         await asyncio.sleep(1)
     await super().start(start_urwid=interactive)
     if not interactive:
         self.select_initial_screen()