diff --git a/tests/profiles/test_locator.py b/tests/profiles/test_locator.py new file mode 100644 index 0000000..1b2797c --- /dev/null +++ b/tests/profiles/test_locator.py @@ -0,0 +1,63 @@ +import unittest +import os +import shutil +import tempfile +from tuned.profiles.locator import Locator + +class LocatorTestCase(unittest.TestCase): + def setUp(self): + self.locator = Locator(self._tmp_load_dirs) + + @classmethod + def setUpClass(cls): + tmpdir1 = tempfile.mkdtemp() + tmpdir2 = tempfile.mkdtemp() + cls._tmp_load_dirs = [tmpdir1, tmpdir2] + + cls._create_profile(tmpdir1, "balanced") + cls._create_profile(tmpdir1, "powersafe") + cls._create_profile(tmpdir2, "custom") + cls._create_profile(tmpdir2, "balanced") + + @classmethod + def tearDownClass(cls): + for tmp_dir in cls._tmp_load_dirs: + shutil.rmtree(tmp_dir, True) + + @classmethod + def _create_profile(cls, load_dir, profile_name): + profile_dir = os.path.join(load_dir, profile_name) + conf_name = os.path.join(profile_dir, "tuned.conf") + os.mkdir(profile_dir) + with open(conf_name, "w") as conf_file: + pass + + def test_init(self): + Locator([]) + + def test_init_invalid_type(self): + with self.assertRaises(TypeError): + Locator("string") + + def test_get_known_names(self): + known = self.locator.get_known_names() + self.assertListEqual(known, ["balanced", "custom", "powersafe"]) + + def test_get_config(self): + config_name = self.locator.get_config("custom") + self.assertEquals(config_name, os.path.join(self._tmp_load_dirs[1], "custom", "tuned.conf")) + + def test_get_config_priority(self): + customized = self.locator.get_config("balanced") + self.assertEquals(customized, os.path.join(self._tmp_load_dirs[1], "balanced", "tuned.conf")) + system = self.locator.get_config("balanced", [customized]) + self.assertEquals(system, os.path.join(self._tmp_load_dirs[0], "balanced", "tuned.conf")) + none = self.locator.get_config("balanced", [customized, system]) + self.assertIsNone(none) + + def test_ignore_nonexistent_dirs(self): + locator = Locator([self._tmp_load_dirs[0], "/tmp/some-dir-which-does-not-exist-for-sure"]) + balanced = locator.get_config("balanced") + self.assertEquals(balanced, os.path.join(self._tmp_load_dirs[0], "balanced", "tuned.conf")) + known = locator.get_known_names() + self.assertListEqual(known, ["balanced", "powersafe"]) diff --git a/tuned/profiles/__init__.py b/tuned/profiles/__init__.py index f5d8585..22cd0df 100644 --- a/tuned/profiles/__init__.py +++ b/tuned/profiles/__init__.py @@ -1,3 +1,4 @@ +from tuned.profiles.locator import * from tuned.profiles.loader import * from tuned.profiles.profile import * from tuned.profiles.unit import * diff --git a/tuned/profiles/loader.py b/tuned/profiles/loader.py index 6c57e0a..0a6e3d6 100644 --- a/tuned/profiles/loader.py +++ b/tuned/profiles/loader.py @@ -11,27 +11,24 @@ class Loader(object): Profiles loader. """ - __slots__ = ["_load_directories", "_profile_merger", "_profile_factory"] + __slots__ = ["_profile_locator", "_profile_merger", "_profile_factory"] - def __init__(self, load_directories, profile_factory, profile_merger): - if type(load_directories) is not list: - raise TypeError("load_directories parameter is not a list") - - self._load_directories = load_directories + def __init__(self, profile_locator, profile_factory, profile_merger): + self._profile_locator = profile_locator self._profile_factory = profile_factory self._profile_merger = profile_merger def _create_profile(self, profile_name, config): return tuned.profiles.profile.Profile(profile_name, config) - @property - def load_directories(self): - return self._load_directories - @classmethod def safe_name(cls, profile_name): return re.match(r'^[a-zA-Z0-9_.-]+$', profile_name) + @property + def profile_locator(self): + return self._profile_locator + def load(self, profile_names): if type(profile_names) is not list: profile_names = profile_names.split() @@ -54,7 +51,7 @@ def load(self, profile_names): def _load_profile(self, profile_names, profiles, processed_files): for name in profile_names: - filename = self._find_config_file(name, processed_files) + filename = self._profile_locator.get_config(name, processed_files) if filename is None: raise InvalidProfileException("Cannot find profile '%s' in '%s'." % (name, list(reversed(self._load_directories)))) processed_files.append(filename) @@ -67,17 +64,6 @@ def _load_profile(self, profile_names, profiles, processed_files): profiles.append(profile) - def _find_config_file(self, profile_name, skip_files=None): - for dir_name in reversed(self._load_directories): - config_file = os.path.join(dir_name, profile_name, "tuned.conf") - config_file = os.path.normpath(config_file) - - if skip_files is not None and config_file in skip_files: - continue - - if os.path.exists(config_file): - return config_file - def _load_config_data(self, file_name): parser = ConfigParser.SafeConfigParser(allow_no_value=True) try: diff --git a/tuned/profiles/locator.py b/tuned/profiles/locator.py new file mode 100644 index 0000000..1bfa99d --- /dev/null +++ b/tuned/profiles/locator.py @@ -0,0 +1,47 @@ +import os + +class Locator(object): + """ + Profiles locator and enumerator. + """ + + __slots__ = ["_load_directories"] + + def __init__(self, load_directories): + if type(load_directories) is not list: + raise TypeError("load_directories parameter is not a list") + self._load_directories = load_directories + + @property + def load_directories(self): + return self._load_directories + + def _get_config_filename(self, *path_parts): + path_parts = list(path_parts) + ["tuned.conf"] + config_name = os.path.join(*path_parts) + return os.path.normpath(config_name) + + def get_config(self, profile_name, skip_files=None): + for dir_name in reversed(self._load_directories): + config_file = self._get_config_filename(dir_name, profile_name) + + if skip_files is not None and config_file in skip_files: + continue + + if os.path.isfile(config_file): + return config_file + + return None + + def get_known_names(self): + profiles = set() + for dir_name in self._load_directories: + try: + for profile_name in os.listdir(dir_name): + config_file = self._get_config_filename(dir_name, profile_name) + if os.path.isfile(config_file): + profiles.add(profile_name) + except OSError: + pass + + return sorted(list(profiles))