def exec_readlines_test_filter_stderr(self): """Test execReadlines and filter_stderr.""" # Test that stderr is normally included with tempfile.NamedTemporaryFile(mode="w+t") as testscript: testscript.write("""#!/bin/sh echo "one" echo "two" >&2 echo "three" exit 0 """) testscript.flush() with timer(5): rl_iterator = util.execReadlines("/bin/sh", [testscript.name]) self.assertEqual(next(rl_iterator), "one") self.assertEqual(next(rl_iterator), "two") self.assertEqual(next(rl_iterator), "three") self.assertRaises(StopIteration, rl_iterator.__next__) # Test that filter stderr removes the middle line with tempfile.NamedTemporaryFile(mode="w+t") as testscript: testscript.write("""#!/bin/sh echo "one" echo "two" >&2 echo "three" exit 0 """) testscript.flush() with timer(5): rl_iterator = util.execReadlines("/bin/sh", [testscript.name], filter_stderr=True) self.assertEqual(next(rl_iterator), "one") self.assertEqual(next(rl_iterator), "three") self.assertRaises(StopIteration, rl_iterator.__next__)
def test_exec_readlines_signals(self): """Test execReadlines and signal receipt.""" # ignored signal old_HUP_handler = signal.signal(signal.SIGHUP, signal.SIG_IGN) try: with tempfile.NamedTemporaryFile(mode="wt") as testscript: testscript.write("""#!/bin/sh echo "one" kill -HUP $PPID echo "two" echo -n "three" exit 0 """) testscript.flush() with timer(5): rl_iterator = util.execReadlines("/bin/sh", [testscript.name]) assert next(rl_iterator) == "one" assert next(rl_iterator) == "two" assert next(rl_iterator) == "three" with pytest.raises(StopIteration): rl_iterator.__next__() finally: signal.signal(signal.SIGHUP, old_HUP_handler) # caught signal def _hup_handler(signum, frame): pass old_HUP_handler = signal.signal(signal.SIGHUP, _hup_handler) try: with tempfile.NamedTemporaryFile(mode="wt") as testscript: testscript.write("""#!/bin/sh echo "one" kill -HUP $PPID echo "two" echo -n "three" exit 0 """) testscript.flush() with timer(5): rl_iterator = util.execReadlines("/bin/sh", [testscript.name]) assert next(rl_iterator) == "one" assert next(rl_iterator) == "two" assert next(rl_iterator) == "three" with pytest.raises(StopIteration): rl_iterator.__next__() finally: signal.signal(signal.SIGHUP, old_HUP_handler)
def test_exec_readlines(self): """Test execReadlines.""" # test no lines are returned assert list(util.execReadlines("true", [])) == [] # test some lines are returned assert len(list(util.execReadlines("ls", ["--help"]))) > 0 # check that it always returns an iterator for both # if there is some output and if there isn't any assert hasattr(util.execReadlines("ls", ["--help"]), "__iter__") assert hasattr(util.execReadlines("true", []), "__iter__")
def exec_readlines_test(self): """Test execReadlines.""" # test no lines are returned self.assertEqual(list(util.execReadlines("true", [])), []) # test some lines are returned self.assertGreater(len(list(util.execReadlines("ls", ["--help"]))), 0) # check that it always returns an iterator for both # if there is some output and if there isn't any self.assertTrue(hasattr(util.execReadlines("ls", ["--help"]), "__iter__")) self.assertTrue(hasattr(util.execReadlines("true", []), "__iter__"))
def exec_readlines_test_signals(self): """Test execReadlines and signal receipt.""" # ignored signal old_HUP_handler = signal.signal(signal.SIGHUP, signal.SIG_IGN) try: with tempfile.NamedTemporaryFile(mode="wt") as testscript: testscript.write("""#!/bin/sh echo "one" kill -HUP $PPID echo "two" echo -n "three" exit 0 """) testscript.flush() with timer(5): rl_iterator = util.execReadlines("/bin/sh", [testscript.name]) self.assertEqual(next(rl_iterator), "one") self.assertEqual(next(rl_iterator), "two") self.assertEqual(next(rl_iterator), "three") self.assertRaises(StopIteration, rl_iterator.__next__) finally: signal.signal(signal.SIGHUP, old_HUP_handler) # caught signal def _hup_handler(signum, frame): pass old_HUP_handler = signal.signal(signal.SIGHUP, _hup_handler) try: with tempfile.NamedTemporaryFile(mode="wt") as testscript: testscript.write("""#!/bin/sh echo "one" kill -HUP $PPID echo "two" echo -n "three" exit 0 """) testscript.flush() with timer(5): rl_iterator = util.execReadlines("/bin/sh", [testscript.name]) self.assertEqual(next(rl_iterator), "one") self.assertEqual(next(rl_iterator), "two") self.assertEqual(next(rl_iterator), "three") self.assertRaises(StopIteration, rl_iterator.__next__) finally: signal.signal(signal.SIGHUP, old_HUP_handler)
def exec_readlines_auto_kill_test(self): """Test execReadlines with reading only part of the output""" with tempfile.NamedTemporaryFile(mode="w+t") as testscript: testscript.write("""#!/bin/sh # Output forever while true; do echo hey done """) testscript.flush() with timer(5): rl_iterator = util.execReadlines("/bin/sh", [testscript.name]) # Save the process context proc = rl_iterator._proc # Read two lines worth self.assertEqual(next(rl_iterator), "hey") self.assertEqual(next(rl_iterator), "hey") # Delete the iterator and wait for the process to be killed del rl_iterator proc.communicate() # Check that the process is gone self.assertIsNotNone(proc.poll())
def test_exec_readlines_auto_kill(self): """Test execReadlines with reading only part of the output""" with tempfile.NamedTemporaryFile(mode="w+t") as testscript: testscript.write("""#!/bin/sh # Output forever while true; do echo hey done """) testscript.flush() with timer(5): rl_iterator = util.execReadlines("/bin/sh", [testscript.name]) # Save the process context proc = rl_iterator._proc # Read two lines worth assert next(rl_iterator) == "hey" assert next(rl_iterator) == "hey" # Delete the iterator and wait for the process to be killed del rl_iterator proc.communicate() # Check that the process is gone assert proc.poll() is not None
def get_doc_type(file_path): try: for line in execReadlines("oscap", ["info", file_path]): if line.startswith("Document type:"): _prefix, _sep, type_info = line.partition(":") return type_info.strip() except OSError: # 'oscap info' exitted with a non-zero exit code -> unknown doc # type return None
def journalctl_callback(): """Callback to get logs from journalctl.""" # regex to filter log messages from anaconda's process (we have that in our # logs) anaconda_log_line = re.compile(r"\[%d\]:" % os.getpid()) ret = "" for line in util.execReadlines("journalctl", ["-b"]): if anaconda_log_line.search(line) is None: # not an anaconda's message ret += line + "\n" return ret
def test_exec_readlines_normal_output(self): """Test the output of execReadlines.""" # Test regular-looking output with tempfile.NamedTemporaryFile(mode="w+t") as testscript: testscript.write("""#!/bin/sh echo "one" echo "two" echo "three" exit 0 """) testscript.flush() with timer(5): rl_iterator = util.execReadlines("/bin/sh", [testscript.name]) assert next(rl_iterator) == "one" assert next(rl_iterator) == "two" assert next(rl_iterator) == "three" with pytest.raises(StopIteration): rl_iterator.__next__() # Test output with no end of line with tempfile.NamedTemporaryFile(mode="w+t") as testscript: testscript.write("""#!/bin/sh echo "one" echo "two" echo -n "three" exit 0 """) testscript.flush() with timer(5): rl_iterator = util.execReadlines("/bin/sh", [testscript.name]) assert next(rl_iterator) == "one" assert next(rl_iterator) == "two" assert next(rl_iterator) == "three" with pytest.raises(StopIteration): rl_iterator.__next__()
def run_grubby(args=None): """ Run grubby and retrieve the kernel, initrd and boot arguments :param list args: Arguments to pass to grubby. :returns: kernel path, initrd path, root device, kernel cmdline args. :rtype: namedtuple :raises: some error on failure The returned namedtuple contains the following attributes: kernel, initrd, root, args """ boot_info_fields = ["kernel", "initrd", "root", "args"] boot_info_class = namedtuple("BootInfo", boot_info_fields) boot_info_args = {} if not args: args = ["--info", "DEFAULT"] # Run grubby and fill in the boot_info with the first values seen, exit the # loop when all of the needed values have been gathered. try: for line in execReadlines("grubby", args, root=conf.target.system_root): key, _sep, value = line.partition("=") value = unquote(value) if key in boot_info_fields: boot_info_args[key] = value boot_info_fields.remove(key) if not boot_info_fields: break except OSError as e: log.error("run_grubby failed: %s", e) raise GrubbyInfoError(e) if boot_info_fields: raise GrubbyInfoError("Missing values: %s" % ", ".join(boot_info_fields)) # There could be multiple initrd images defined for a boot entry, but # the kexec command line tool only supports passing a single initrd. if "initrd" in boot_info_args: boot_info_args["initrd"] = boot_info_args["initrd"].split(" ")[0] boot_info = boot_info_class(**boot_info_args) log.info("grubby boot info for (%s): %s", args, boot_info) return boot_info
def get_locale_map_from_ostree(repo, ref): """Get a map of languages and locales from the given OSTree. For example: {"en": ["en_US"]} :param repo: the OSTree repository url :param ref: the name of branch inside the repository :return: a map of languages and locales """ # Fallback to just en_US in case of errors. locale_map = {"en": ["en_US"]} # Let's only handle local embedded repos for now. Anyway, it'd probably # not be very common to only override ostreesetup through kickstart and # still want the interactive installer. Though to be nice, let's handle # that case. if not repo.startswith("file://"): log.info("ostree repo is not local; defaulting to en_US") return # Convert to regular UNIX path. repo = repo[len("file://"):] util.mkdirChain(os.path.join(repo, "tmp/usr/lib")) rc = util.execWithRedirect("/usr/bin/ostree", [ "checkout", "--repo", repo, ref, "--subpath", "/usr/lib/locale/locale-archive", "%s/tmp/usr/lib/locale" % repo ]) if rc != 0: log.error("failed to check out locale-archive; check program.log") return for line in util.execReadlines( "/usr/bin/localedef", ["--prefix", os.path.join(repo, "tmp"), "--list-archive"]): line = strip_codeset_and_modifier(line) if '_' in line: (lang, _territory) = line.split('_', 1) else: lang = line if lang not in locale_map: locale_map[lang] = [line] else: locale_map[lang].append(line) # Nuke the checkout for good measure. shutil.rmtree(os.path.join(repo, "tmp/usr")) return locale_map
def exec_readlines_test_normal_output(self): """Test the output of execReadlines.""" # Test regular-looking output with tempfile.NamedTemporaryFile(mode="w+t") as testscript: testscript.write("""#!/bin/sh echo "one" echo "two" echo "three" exit 0 """) testscript.flush() with timer(5): rl_iterator = util.execReadlines("/bin/sh", [testscript.name]) self.assertEqual(next(rl_iterator), "one") self.assertEqual(next(rl_iterator), "two") self.assertEqual(next(rl_iterator), "three") self.assertRaises(StopIteration, rl_iterator.__next__) # Test output with no end of line with tempfile.NamedTemporaryFile(mode="w+t") as testscript: testscript.write("""#!/bin/sh echo "one" echo "two" echo -n "three" exit 0 """) testscript.flush() with timer(5): rl_iterator = util.execReadlines("/bin/sh", [testscript.name]) self.assertEqual(next(rl_iterator), "one") self.assertEqual(next(rl_iterator), "two") self.assertEqual(next(rl_iterator), "three") self.assertRaises(StopIteration, rl_iterator.__next__)
def get_locale_map_from_ostree(repo, ref): """Get a map of languages and locales from the given OSTree. For example: {"en": ["en_US"]} :param repo: the OSTree repository url :param ref: the name of branch inside the repository :return: a map of languages and locales """ # Fallback to just en_US in case of errors. locale_map = {"en": ["en_US"]} # Let's only handle local embedded repos for now. Anyway, it'd probably # not be very common to only override ostreesetup through kickstart and # still want the interactive installer. Though to be nice, let's handle # that case. if not repo.startswith("file://"): log.info("ostree repo is not local; defaulting to en_US") return # Convert to regular UNIX path. repo = repo[len("file://"):] util.mkdirChain(os.path.join(repo, "tmp/usr/lib")) rc = util.execWithRedirect("/usr/bin/ostree", ["checkout", "--repo", repo, ref, "--subpath", "/usr/lib/locale/locale-archive", "%s/tmp/usr/lib/locale" % repo]) if rc != 0: log.error("failed to check out locale-archive; check program.log") return for line in util.execReadlines("/usr/bin/localedef", ["--prefix", os.path.join(repo, "tmp"), "--list-archive"]): line = strip_codeset_and_modifier(line) if '_' in line: (lang, _territory) = line.split('_', 1) else: lang = line if lang not in locale_map: locale_map[lang] = [line] else: locale_map[lang].append(line) # Nuke the checkout for good measure. shutil.rmtree(os.path.join(repo, "tmp/usr")) return locale_map
def _initialize_localemap(self, ref, repo): if self.localemap: return # fallback to just en_US in case of errors self.localemap = {"en": ["en_US"]} # Let's only handle local embedded repos for now. Anyway, it'd probably # not be very common to only override ostreesetup through kickstart and # still want the interactive installer. Though to be nice, let's handle # that case. if not repo.startswith("file://"): log.info("ostree repo is not local; defaulting to en_US") return # convert to regular UNIX path repo = repo[len("file://"):] util.mkdirChain(os.path.join(repo, "tmp/usr/lib")) rc = util.execWithRedirect("/usr/bin/ostree", [ "checkout", "--repo", repo, ref, "--subpath", "/usr/lib/locale/locale-archive", "%s/tmp/usr/lib/locale" % repo ]) if rc != 0: log.error("failed to check out locale-archive; check program.log") return for line in util.execReadlines( "/usr/bin/localedef", ["--prefix", os.path.join(repo, "tmp"), "--list-archive"]): line = self._strip_codeset_and_modifier(line) if '_' in line: (lang, _territory) = line.split('_', 1) else: lang = line if lang not in self.localemap: self.localemap[lang] = [line] else: self.localemap[lang].append(line) # nuke the checkout for good measure shutil.rmtree(os.path.join(repo, "tmp/usr"))
def run_grubby(args=None): """ Run grubby and retrieve the kernel, initrd and boot arguments :param list args: Arguments to pass to grubby. :returns: kernel path, initrd path, root device, kernel cmdline args. :rtype: namedtuple :raises: some error on failure The returned namedtuple contains the following attributes: kernel, initrd, root, args """ boot_info_fields = ["kernel", "initrd", "root", "args"] boot_info_class = namedtuple("BootInfo", boot_info_fields) boot_info_args = {} if not args: args = ["--info", "DEFAULT"] # Run grubby and fill in the boot_info with the first values seen, exit the # loop when all of the needed values have been gathered. try: for line in execReadlines("grubby", args, root=getSysroot()): key, _sep, value = line.partition("=") value = unquote(value) if key in boot_info_fields: boot_info_args[key] = value boot_info_fields.remove(key) if not boot_info_fields: break except OSError as e: log.error("run_grubby failed: %s", e) raise GrubbyInfoError(e) if boot_info_fields: raise GrubbyInfoError("Missing values: %s" % ", ".join(boot_info_fields)) boot_info = boot_info_class(**boot_info_args) log.info("grubby boot info for (%s): %s", args, boot_info) return boot_info
def run_grubby(args=None): """ Run grubby and retrieve the kernel, initrd and boot arguments :param list args: Arguments to pass to grubby. :returns: kernel path, initrd path, root device, kernel cmdline args. :rtype: namedtuple :raises: some error on failure The returned namedtuple contains the following attributes: kernel, initrd, root, args """ boot_info = _BootInfo() attrs = list(_BootInfo._fields) if not args: args = ["--info", "DEFAULT"] # Run grubby and fill in the boot_info with the first values seen, exit the # loop when all of the needed values have been gathered. try: for line in execReadlines("grubby", args, root=getSysroot()): key, _sep, value = line.partition("=") value = unquote(value) if key in attrs: setattr(boot_info, key, value) attrs.remove(key) if not attrs: break except OSError as e: log.error("run_grubby failed: %s", e) raise GrubbyInfoError(e) if len(attrs) > 0: raise GrubbyInfoError("Missing values: %s" % ", ".join(attrs)) log.info("grubby boot info for (%s): %s", args, boot_info) return boot_info
def get_doc_type(file_path): content_type = "unknown" try: for line in execReadlines("oscap", ["info", file_path]): if line.startswith("Document type:"): _prefix, _sep, type_info = line.partition(":") content_type = type_info.strip() break except OSError: # 'oscap info' exitted with a non-zero exit code -> unknown doc # type pass except UnicodeDecodeError: # 'oscap info' supplied weird output, which happens when it tries # to explain why it can't examine e.g. a JPG. pass except Exception as e: log.warning( f"OSCAP addon: Unexpected error when looking at {file_path}: {str(e)}" ) log.info("OSCAP addon: Identified {file_path} as {content_type}".format( file_path=file_path, content_type=content_type)) return content_type
def test_exec_readlines_exits(self): """Test execReadlines in different child exit situations.""" # Tests that exit on signal will raise OSError once output # has been consumed, otherwise the test will exit normally. # Test a normal, non-0 exit with tempfile.NamedTemporaryFile(mode="wt") as testscript: testscript.write("""#!/bin/sh echo "one" echo "two" echo "three" exit 1 """) testscript.flush() with timer(5): rl_iterator = util.execReadlines("/bin/sh", [testscript.name]) assert next(rl_iterator) == "one" assert next(rl_iterator) == "two" assert next(rl_iterator) == "three" with pytest.raises(OSError): rl_iterator.__next__() # Test exit on signal with tempfile.NamedTemporaryFile(mode="wt") as testscript: testscript.write("""#!/bin/sh echo "one" echo "two" echo "three" kill -TERM $$ """) testscript.flush() with timer(5): rl_iterator = util.execReadlines("/bin/sh", [testscript.name]) assert next(rl_iterator) == "one" assert next(rl_iterator) == "two" assert next(rl_iterator) == "three" with pytest.raises(OSError): rl_iterator.__next__() # Repeat the above two tests, but exit before a final newline with tempfile.NamedTemporaryFile(mode="wt") as testscript: testscript.write("""#!/bin/sh echo "one" echo "two" echo -n "three" exit 1 """) testscript.flush() with timer(5): rl_iterator = util.execReadlines("/bin/sh", [testscript.name]) assert next(rl_iterator) == "one" assert next(rl_iterator) == "two" assert next(rl_iterator) == "three" with pytest.raises(OSError): rl_iterator.__next__() with tempfile.NamedTemporaryFile(mode="wt") as testscript: testscript.write("""#!/bin/sh echo "one" echo "two" echo -n "three" kill -TERM $$ """) testscript.flush() with timer(5): rl_iterator = util.execReadlines("/bin/sh", [testscript.name]) assert next(rl_iterator) == "one" assert next(rl_iterator) == "two" assert next(rl_iterator) == "three" with pytest.raises(OSError): rl_iterator.__next__()
def exec_readlines_test_exits(self): """Test execReadlines in different child exit situations.""" # Tests that exit on signal will raise OSError once output # has been consumed, otherwise the test will exit normally. # Test a normal, non-0 exit with tempfile.NamedTemporaryFile(mode="wt") as testscript: testscript.write("""#!/bin/sh echo "one" echo "two" echo "three" exit 1 """) testscript.flush() with timer(5): rl_iterator = util.execReadlines("/bin/sh", [testscript.name]) self.assertEqual(next(rl_iterator), "one") self.assertEqual(next(rl_iterator), "two") self.assertEqual(next(rl_iterator), "three") self.assertRaises(OSError, rl_iterator.__next__) # Test exit on signal with tempfile.NamedTemporaryFile(mode="wt") as testscript: testscript.write("""#!/bin/sh echo "one" echo "two" echo "three" kill -TERM $$ """) testscript.flush() with timer(5): rl_iterator = util.execReadlines("/bin/sh", [testscript.name]) self.assertEqual(next(rl_iterator), "one") self.assertEqual(next(rl_iterator), "two") self.assertEqual(next(rl_iterator), "three") self.assertRaises(OSError, rl_iterator.__next__) # Repeat the above two tests, but exit before a final newline with tempfile.NamedTemporaryFile(mode="wt") as testscript: testscript.write("""#!/bin/sh echo "one" echo "two" echo -n "three" exit 1 """) testscript.flush() with timer(5): rl_iterator = util.execReadlines("/bin/sh", [testscript.name]) self.assertEqual(next(rl_iterator), "one") self.assertEqual(next(rl_iterator), "two") self.assertEqual(next(rl_iterator), "three") self.assertRaises(OSError, rl_iterator.__next__) with tempfile.NamedTemporaryFile(mode="wt") as testscript: testscript.write("""#!/bin/sh echo "one" echo "two" echo -n "three" kill -TERM $$ """) testscript.flush() with timer(5): rl_iterator = util.execReadlines("/bin/sh", [testscript.name]) self.assertEqual(next(rl_iterator), "one") self.assertEqual(next(rl_iterator), "two") self.assertEqual(next(rl_iterator), "three") self.assertRaises(OSError, rl_iterator.__next__)