def run(self, connection, args=None): # Prompts commonly include # - when logging such strings, # use lazy logging or the string will not be quoted correctly. def check_prompt_characters(prompt): if not any([True for c in DISTINCTIVE_PROMPT_CHARACTERS if c in prompt]): self.logger.warning(self.check_prompt_characters_warning, prompt) connection.prompt_str = LinuxKernelMessages.get_init_prompts() # Skip auto login if the configuration is not found params = self.parameters.get('auto_login', None) if params is None: self.logger.debug("Skipping of auto login") else: self.logger.debug("Waiting for the login prompt") connection.prompt_str.append(params['login_prompt']) self.logger.debug(connection.prompt_str) results = LinuxKernelMessages.parse_failures(connection) if len(results) > 1: self.results = {'fail': results} return connection else: connection.sendline(params['username'], delay=self.character_delay) if 'password_prompt' in params: self.logger.debug("Waiting for password prompt") connection.prompt_str = params['password_prompt'] self.wait(connection) connection.sendline(params['password'], delay=self.character_delay) # prompt_str can be a list or str if isinstance(connection.prompt_str, str): connection.prompt_str = [DEFAULT_SHELL_PROMPT] else: connection.prompt_str.extend([DEFAULT_SHELL_PROMPT]) prompts = self.parameters.get('prompts', None) if isinstance(prompts, list): for prompt in prompts: check_prompt_characters(prompt) connection.prompt_str.extend(prompts) else: check_prompt_characters(prompts) connection.prompt_str.append(prompts) self.logger.debug("Setting shell prompt(s) to %s" % connection.prompt_str) # pylint: disable=logging-not-lazy if params is None: self.logger.debug("Parsing kernel messages") parsed = LinuxKernelMessages.parse_failures(connection) if len(parsed) and 'success' in parsed[0]: self.results = {'success': parsed[0]} else: self.results = {'fail': parsed} connection.sendline('export PS1="%s"' % DEFAULT_SHELL_PROMPT, delay=self.character_delay) return connection
def test_kernel_4(self): logfile = os.path.join(os.path.dirname(__file__), 'kernel-4.txt') self.assertTrue(os.path.exists(logfile)) child = pexpect.spawn('cat', [logfile]) message_list = LinuxKernelMessages.get_init_prompts() self.assertIsNotNone(message_list) connection = FakeConnection(child, message_list) results = LinuxKernelMessages.parse_failures( connection, max_end_time=self.max_end_time) self.assertIn('Stack', results[0]['message'].decode('utf-8')) self.assertIn('Kernel panic', results[1]['message'].decode('utf-8'))
def test_kernel_ramdisk_alert(self): logfile = os.path.join(os.path.dirname(__file__), "kernel-3.txt") self.assertTrue(os.path.exists(logfile)) child = pexpect.spawn("cat", [logfile]) message_list = LinuxKernelMessages.get_init_prompts() self.assertIsNotNone(message_list) connection = FakeConnection(child, message_list) results = LinuxKernelMessages.parse_failures(connection) self.assertEqual(len(list(results)), 1) self.assertIn("message", results[0]) self.assertIn("success", results[0]) self.assertNotIn("panic", results[0])
def test_kernel_ramdisk_alert(self): logfile = os.path.join(os.path.dirname(__file__), 'kernel-3.txt') self.assertTrue(os.path.exists(logfile)) child = pexpect.spawn('cat', [logfile]) message_list = LinuxKernelMessages.get_init_prompts() self.assertIsNotNone(message_list) connection = FakeConnection(child, message_list) results = LinuxKernelMessages.parse_failures(connection) self.assertEqual(len(list(results)), 1) self.assertIn('message', results[0]) self.assertIn('success', results[0]) self.assertNotIn('panic', results[0])
def test_kernel_1(self): logfile = os.path.join(os.path.dirname(__file__), 'kernel-1.txt') self.assertTrue(os.path.exists(logfile)) child = pexpect.spawn('cat', [logfile]) message_list = LinuxKernelMessages.get_kernel_prompts() connection = FakeConnection(child, message_list) results = LinuxKernelMessages.parse_failures( connection, max_end_time=self.max_end_time) self.assertEqual(len(results), 1) self.assertEqual( results[0], { 'message': 'kernel-messages', 'success': 'Freeing unused kernel memory' })
def test_kernel_2(self): logfile = os.path.join(os.path.dirname(__file__), 'kernel-2.txt') self.assertTrue(os.path.exists(logfile)) child = pexpect.spawn('cat', [logfile]) message_list = LinuxKernelMessages.get_kernel_prompts() self.assertIsNotNone(message_list) connection = FakeConnection(child, message_list) results = LinuxKernelMessages.parse_failures(connection) # traces as far as da227214a82491bf occur before Freeing init memory: self.assertEqual(len(list(results)), 9) message_list = LinuxKernelMessages.get_init_prompts() connection.prompt_str = message_list results = LinuxKernelMessages.parse_failures(connection) # 5 more traces appear during init self.assertEqual(len(list(results)), 5)
def test_kernel_2(self): logfile = os.path.join(os.path.dirname(__file__), "kernel-2.txt") self.assertTrue(os.path.exists(logfile)) child = pexpect.spawn("cat", [logfile]) message_list = LinuxKernelMessages.get_kernel_prompts() self.assertIsNotNone(message_list) connection = FakeConnection(child, message_list) results = LinuxKernelMessages.parse_failures(connection) # traces as far as da227214a82491bf occur before Freeing init memory: self.assertEqual(len(list(results)), 9) message_list = LinuxKernelMessages.get_init_prompts() connection.prompt_str = message_list results = LinuxKernelMessages.parse_failures(connection) # 5 more traces appear during init self.assertEqual(len(list(results)), 5)
def prepare_test_connection(): logfile = os.path.join(os.path.dirname(__file__), 'kernel.txt') if not os.path.exists(logfile): raise OSError("Missing test support file.") child = pexpect.spawn('cat', [logfile]) message_list = LinuxKernelMessages.get_kernel_prompts() return FakeConnection(child, message_list)
def prepare_test_connection(): logfile = os.path.join(os.path.dirname(__file__), 'kernel.txt') if not os.path.exists(logfile): raise OSError("Missing test support file.") child = pexpect.spawn('cat', [logfile]) message_list = LinuxKernelMessages.get_kernel_prompts() return FakeConnection(child, message_list)
def run(self, prompt_list): if not self.existing_prompt: self.existing_prompt = prompt_list[:] prompt_list = LinuxKernelMessages.get_kernel_prompts() if isinstance(self.existing_prompt, list): prompt_list.extend(self.existing_prompt) else: prompt_list.append(self.existing_prompt) return prompt_list
def run(self, prompt_list): if not self.existing_prompt: self.existing_prompt = prompt_list[:] prompt_list = LinuxKernelMessages.get_kernel_prompts() if isinstance(self.existing_prompt, list): prompt_list.extend(self.existing_prompt) else: prompt_list.append(self.existing_prompt) return prompt_list
def run(self, prompt_list): if KERNEL_FREE_INIT_MSG in prompt_list: index = prompt_list.index(KERNEL_FREE_INIT_MSG) if len(prompt_list) > index: index += 1 self.existing_prompt = prompt_list[index:] else: self.existing_prompt = prompt_list[:] prompt_list = LinuxKernelMessages.get_init_prompts() super(Child, self).run(prompt_list) return prompt_list
def populate(self, parameters): self.internal_pipeline = Pipeline(parent=self, job=self.job, parameters=parameters) self.internal_pipeline.add_action(BootQemuRetry()) self.internal_pipeline.add_action(LinuxKernelMessages()) # Add AutoLoginAction unconditionally as this action does nothing if # the configuration does not contain 'auto_login' self.internal_pipeline.add_action(AutoLoginAction()) self.internal_pipeline.add_action(ExpectShellSession()) self.internal_pipeline.add_action(ExportDeviceEnvironment())
def run(self, prompt_list): if KERNEL_FREE_INIT_MSG in prompt_list: index = prompt_list.index(KERNEL_FREE_INIT_MSG) if len(prompt_list) > index: index += 1 self.existing_prompt = prompt_list[index:] else: self.existing_prompt = prompt_list[:] prompt_list = LinuxKernelMessages.get_init_prompts() super(Child, self).run(prompt_list) return prompt_list
def test_kernel_txt(self): """ The same logfile passes kernel boot and fails to find init - so the panic needs to be caught by InitMessages """ logfile = os.path.join(os.path.dirname(__file__), 'kernel-panic.txt') self.assertTrue(os.path.exists(logfile)) child = pexpect.spawn('cat', [logfile]) message_list = LinuxKernelMessages.get_kernel_prompts() self.assertIsNotNone(message_list) self.assertIn(LinuxKernelMessages.MESSAGE_CHOICES[0][1], message_list) self.assertIn(LinuxKernelMessages.MESSAGE_CHOICES[1][1], message_list) self.assertIn(LinuxKernelMessages.MESSAGE_CHOICES[2][1], message_list) self.assertIn(LinuxKernelMessages.MESSAGE_CHOICES[3][1], message_list) self.assertIn(LinuxKernelMessages.MESSAGE_CHOICES[4][1], message_list) self.assertIn(LinuxKernelMessages.MESSAGE_CHOICES[5][1], message_list) connection = FakeConnection(child, message_list) result = LinuxKernelMessages.parse_failures( connection, max_end_time=self.max_end_time) self.assertEqual(len(result), 2) self.assertIn('success', result[0]) self.assertIn('panic', result[1]) self.assertEqual(result[0]['success'], KERNEL_FREE_UNUSED_MSG) self.assertEqual(result[1]['panic'], KERNEL_PANIC_MSG) self.assertEqual(len(result), 2) self.assertIn('panic', result[1]) self.assertIn('message', result[1]) self.assertTrue('Attempted to kill init' in str(result[1]['message'])) self.assertTrue('(unwind_backtrace) from' in str(result[1]['message'])) message_list = LinuxKernelMessages.get_init_prompts() child = pexpect.spawn('cat', [logfile]) connection = FakeConnection(child, message_list) results = LinuxKernelMessages.parse_failures( connection, max_end_time=self.max_end_time) self.assertEqual(len(results), 1) self.assertIn('panic', result[1]) self.assertIn('message', result[1]) self.assertTrue('Attempted to kill init' in str(result[1]['message'])) self.assertTrue('(unwind_backtrace) from' in str(result[1]['message']))
def test_kernel_2(self): logfile = os.path.join(os.path.dirname(__file__), 'kernel-2.txt') self.assertTrue(os.path.exists(logfile)) child = pexpect.spawn('cat', [logfile]) message_list = LinuxKernelMessages.get_kernel_prompts() self.assertIsNotNone(message_list) self.assertIn(LinuxKernelMessages.MESSAGE_CHOICES[0][1], message_list) self.assertIn(LinuxKernelMessages.MESSAGE_CHOICES[1][1], message_list) self.assertIn(LinuxKernelMessages.MESSAGE_CHOICES[2][1], message_list) self.assertIn(LinuxKernelMessages.MESSAGE_CHOICES[3][1], message_list) self.assertIn(LinuxKernelMessages.MESSAGE_CHOICES[4][1], message_list) self.assertIn(LinuxKernelMessages.MESSAGE_CHOICES[5][1], message_list) connection = FakeConnection(child, message_list) results = LinuxKernelMessages.parse_failures( connection, max_end_time=self.max_end_time) self.assertEqual(len(list(results)), 14) message_list = LinuxKernelMessages.get_init_prompts() child = pexpect.spawn('cat', [logfile]) connection = FakeConnection(child, message_list) results = LinuxKernelMessages.parse_failures( connection, max_end_time=self.max_end_time) self.assertEqual(len(list(results)), 13)
def test_kernel_txt(self): """ The same logfile passes kernel boot and fails to find init - so the panic needs to be caught by InitMessages """ logfile = os.path.join(os.path.dirname(__file__), "kernel.txt") self.assertTrue(os.path.exists(logfile)) child = pexpect.spawn("cat", [logfile]) message_list = LinuxKernelMessages.get_kernel_prompts() self.assertIsNotNone(message_list) connection = FakeConnection(child, message_list) result = LinuxKernelMessages.parse_failures(connection) self.assertIn("success", result[0]) self.assertEqual(result[0]["success"], KERNEL_FREE_UNUSED_MSG) message_list = LinuxKernelMessages.get_init_prompts() self.assertIn(KERNEL_PANIC_MSG, message_list) self.assertNotIn(KERNEL_FREE_UNUSED_MSG, message_list) connection.prompt_str = message_list result = LinuxKernelMessages.parse_failures(connection) self.assertEqual(len(result), 1) self.assertIn("panic", result[0]) self.assertIn("message", result[0]) self.assertTrue("Attempted to kill init" in str(result[0]["message"])) self.assertTrue("(unwind_backtrace) from" in str(result[0]["message"]))
def check_kernel_messages(self, connection, max_end_time): """ Use the additional pexpect expressions to detect warnings and errors during the kernel boot. Ensure all test jobs using auto-login-action have a result set so that the duration is always available when the action completes successfully. """ if isinstance(connection, SShSession): self.logger.debug("Skipping kernel messages") return self.logger.info("Parsing kernel messages") self.logger.debug(connection.prompt_str) parsed = LinuxKernelMessages.parse_failures(connection, self, max_end_time=max_end_time) if len(parsed) and 'success' in parsed[0]: self.results = {'success': parsed[0]} elif not parsed: self.results = { 'success': "No kernel warnings or errors detected." } else: self.results = {'fail': parsed} self.logger.warning("Kernel warnings or errors detected.")
def run(self, connection, max_end_time, args=None): # Prompts commonly include # - when logging such strings, # use lazy logging or the string will not be quoted correctly. def check_prompt_characters(chk_prompt): if not any([ True for c in DISTINCTIVE_PROMPT_CHARACTERS if c in chk_prompt ]): self.logger.warning(self.check_prompt_characters_warning, chk_prompt) if not connection: return connection prompts = self.parameters.get('prompts', None) for prompt in prompts: check_prompt_characters(prompt) connection.prompt_str = LinuxKernelMessages.get_init_prompts() connection.prompt_str.extend(prompts) # linesep should come from deployment_data as from now on it is OS dependent linesep = self.get_namespace_data(action='deploy-device-env', label='environment', key='line_separator') connection.raw_connection.linesep = linesep if linesep else LINE_SEPARATOR self.logger.debug("Using line separator: #%r#", connection.raw_connection.linesep) # Skip auto login if the configuration is not found params = self.parameters.get('auto_login', None) if not params: self.logger.debug("No login prompt set.") self.force_prompt = True # If auto_login is not enabled, login will time out if login # details are requested. connection.prompt_str.append(LOGIN_TIMED_OUT_MSG) connection.prompt_str.append(LOGIN_INCORRECT_MSG) # wait for a prompt or kernel messages self.check_kernel_messages(connection, max_end_time) if 'success' in self.results: check = self.results['success'].values() if LOGIN_TIMED_OUT_MSG in check or LOGIN_INCORRECT_MSG in check: raise JobError( "auto_login not enabled but image requested login details." ) # clear kernel message prompt patterns connection.prompt_str = list(self.parameters.get('prompts', [])) # already matched one of the prompts else: self.logger.info("Waiting for the login prompt") connection.prompt_str.append(params['login_prompt']) connection.prompt_str.append(LOGIN_INCORRECT_MSG) # wait for a prompt or kernel messages self.check_kernel_messages(connection, max_end_time) if 'success' in self.results: if LOGIN_INCORRECT_MSG in self.results['success'].values(): self.logger.warning( "Login incorrect message matched before the login prompt. " "Please check that the login prompt is correct. Retrying login..." ) self.logger.debug("Sending username %s", params['username']) connection.sendline(params['username'], delay=self.character_delay) # clear the kernel_messages patterns connection.prompt_str = list(self.parameters.get('prompts', [])) if 'password_prompt' in params: self.logger.info("Waiting for password prompt") connection.prompt_str.append(params['password_prompt']) # This can happen if password_prompt is misspelled. connection.prompt_str.append(LOGIN_TIMED_OUT_MSG) # wait for the password prompt index = self.wait(connection, max_end_time) if index: self.logger.debug("Matched prompt #%s: %s", index, connection.prompt_str[index]) if connection.prompt_str[index] == LOGIN_TIMED_OUT_MSG: raise JobError( "Password prompt not matched, please update the job definition with the correct one." ) self.logger.debug("Sending password %s", params['password']) connection.sendline(params['password'], delay=self.character_delay) # clear the Password pattern connection.prompt_str = list(self.parameters.get( 'prompts', [])) connection.prompt_str.append(LOGIN_INCORRECT_MSG) connection.prompt_str.append(LOGIN_TIMED_OUT_MSG) # wait for the login process to provide the prompt index = self.wait(connection, max_end_time) if index: self.logger.debug("Matched %s %s", index, connection.prompt_str[index]) if connection.prompt_str[index] == LOGIN_INCORRECT_MSG: self.errors = LOGIN_INCORRECT_MSG raise JobError(LOGIN_INCORRECT_MSG) if connection.prompt_str[index] == LOGIN_TIMED_OUT_MSG: self.errors = LOGIN_TIMED_OUT_MSG raise JobError(LOGIN_TIMED_OUT_MSG) login_commands = params.get('login_commands', None) if login_commands is not None: self.logger.debug("Running login commands") for command in login_commands: connection.sendline(command) connection.prompt_str.extend( [self.job.device.get_constant('default-shell-prompt')]) self.logger.debug("Setting shell prompt(s) to %s" % connection.prompt_str) # pylint: disable=logging-not-lazy connection.sendline( 'export PS1="%s"' % self.job.device.get_constant('default-shell-prompt'), delay=self.character_delay) return connection