def wait_for_post_boot(self, pre_server): """ Wait for the post-boot environment to come online. :param pre_server: A :class:`ServerDetails` object created by :func:`wait_for_pre_boot()`. """ method_timer = Timer() check_keys = bool(pre_server.host_keys) check_headers = ( self.pre_boot.port_number == self.post_boot.port_number) logger.info( "Waiting for post-boot environment based on SSH %s ..", "host keys" if check_keys else ("server headers" if check_headers else "port numbers")) with AutomaticSpinner("Waiting for post-boot environment", show_time=True): while True: iteration_timer = Timer() if check_headers or check_keys: post_server = self.scan_ssh_server(self.post_boot) if check_keys and post_server.host_keys: logger.verbose( "Checking if SSH host keys have changed ..") if post_server.host_keys != pre_server.host_keys: logger.info("Detected change in SSH host keys.") self.store_host_keys(pre_server, post_server) break if check_headers and pre_server.header and post_server.header: logger.verbose( "Checking if SSH server header has changed ..") if post_server.header != pre_server.header: logger.info( "Detected change in SSH server header.") break elif self.test_ssh_connection(self.post_boot, self.post_context): logger.info("Detected change in SSH port number.") break if method_timer.elapsed_time >= self.boot_timeout: raise BootTimeoutError( format( "Timed out waiting for post-boot environment of %s to come online within %s!", self.post_context, format_timespan(self.boot_timeout), )) iteration_timer.sleep(self.retry_interval) logger.info("Waited %s for post-boot environment.", method_timer)
def wait_for_pre_boot(self): """ Wait for the pre-boot environment to become available. :returns: A :class:`ServerDetails` object. :raises: The following exceptions can be raised: - :exc:`SystemUnreachableError` when :attr:`connect_timeout` seconds have passed and we still haven't managed to query the SSH server in the pre-boot environment. - :exc:`UnlockAbortedError` when the post-boot environment is detected and the operator aborts the unlock sequence. """ method_timer = Timer() logger.info("Waiting for pre-boot environment to become available ..") with AutomaticSpinner("Waiting for pre-boot environment", show_time=True): while True: iteration_timer = Timer() server = self.scan_ssh_server(self.pre_boot) known_keys = self.get_known_host_keys('pre-boot-host-keys') if server.host_keys and known_keys: logger.verbose( "Checking if SSH host keys match known keys ..") if server.host_keys & known_keys: logger.info( "Matched known SSH host keys of pre-boot environment." ) break else: logger.warning( compact(""" Detected post-boot environment while waiting for pre-boot environment to become available, will keep retrying... """)) elif server.match_header('dropbear'): logger.info( "Detected Dropbear in pre-boot environment (as expected)." ) break elif server.match_header('openssh'): logger.warning( compact(""" Detected OpenSSH server while connecting to pre-boot environment where I was expecting Dropbear instead! Could it be that you're accidentally connecting to the post-boot environment? """)) if self.interactive: if prompt_for_confirmation( "Continue connecting anyway?"): logger.info( "Continuing unlock sequence with operator consent .." ) else: raise UnlockAbortedError( "Unlock sequence aborted by operator.") break if method_timer.elapsed_time >= self.connect_timeout: raise SystemUnreachableError( format( "Timed out waiting for pre-boot environment of %s to become available within %s!", self.pre_context, format_timespan(self.connect_timeout), )) iteration_timer.sleep(self.retry_interval) logger.info("Waited %s for pre-boot environment.", method_timer) return server