def test_dbus_name(self): """Test DBus path.""" self.assertEqual(get_dbus_name(), "") self.assertEqual(get_dbus_name("a"), "a") self.assertEqual(get_dbus_name("a", "b"), "a.b") self.assertEqual(get_dbus_name("a", "b", "c"), "a.b.c") self.assertEqual(get_dbus_name("org", "freedesktop", "DBus"), "org.freedesktop.DBus")
def decorator(error_name, namespace=()): error_name = get_dbus_name(*namespace, error_name) def decorated(cls): error_mapper.add_rule( ErrorRule(exception_type=cls, error_name=error_name)) return cls return decorated
def __init__(self, message_bus, service_name): """Creates a module observer. :param message_bus: a message bus :param service_name: a DBus name of a service """ super().__init__(message_bus, service_name) self._proxy = None self._is_addon = service_name.startswith(get_dbus_name(*ADDONS_NAMESPACE)) self._namespace = get_namespace_from_name(service_name) self._object_path = get_dbus_path(*self._namespace)
def __init__(self, namespace, basename=None): """Create an identifier. :param namespace: a sequence of strings :param basename: a string with the base name or None """ if basename: namespace = (*namespace, basename) self._namespace = namespace self._name = get_dbus_name(*namespace) self._path = get_dbus_path(*namespace)
def dbus_error(error_name, namespace=()): """Define decorated class as a DBus error. The decorated exception class will be mapped to a DBus error. :param error_name: a DBus name of the error :param namespace: a sequence of strings :return: a decorator """ error_name = get_dbus_name(*namespace, error_name) def decorated(cls): register.map_exception_to_name(cls, error_name) return cls return decorated
def _find_addons(self): """Find additional modules.""" modules = [] if not self._addons_enabled: return modules dbus = self._message_bus.proxy names = dbus.ListActivatableNames() prefix = get_dbus_name(*ADDONS_NAMESPACE) for service_name in names: if not service_name.startswith(prefix): continue log.debug("Found %s.", service_name) modules.append( ModuleObserver(self._message_bus, service_name, is_addon=True)) return modules
def decorated(cls): name = get_dbus_name(*namespace, interface_name) xml = DBusSpecificationGenerator.generate_specification(cls, name) setattr(cls, DBUS_XML_ATTRIBUTE, xml) return cls
class AnacondaConfigurationTestCase(unittest.TestCase): """Test the Anaconda configuration.""" # Full names of the Anaconda modules. MODULE_NAMES = set( map(lambda s: s.service_name, ( services.TIMEZONE, services.NETWORK, services.LOCALIZATION, services.SECURITY, services.USERS, services.PAYLOADS, services.STORAGE, services.SERVICES, services.SUBSCRIPTION, ))) # Known namespaces of the Anaconda modules. MODULE_NAMESPACES = set( map(lambda n: get_dbus_name(*n), ( namespaces.MODULES_NAMESPACE, namespaces.ADDONS_NAMESPACE, ))) def test_default_configuration(self): # Make sure that we are able to import conf. from pyanaconda.core.configuration.anaconda import conf self.assertEqual(conf.anaconda.debug, False) def test_source(self): conf = AnacondaConfiguration() sources = conf.get_sources() self.assertEqual(sources, []) def test_default_source(self): conf = AnacondaConfiguration.from_defaults() sources = conf.get_sources() self.assertEqual(len(sources), 1) self.assertEqual(sources[0], os.environ.get("ANACONDA_CONFIG_TMP")) def test_default_validation(self): conf = AnacondaConfiguration.from_defaults() conf.validate() # Set invalid value. parser = conf.get_parser() parser["Anaconda"]["debug"] = "string" with self.assertRaises(ConfigurationError): conf.validate() # Remove a required option. parser.remove_option("Anaconda", "debug") with self.assertRaises(ConfigurationError): conf.validate() # Remove a required section. parser.remove_section("Anaconda") with self.assertRaises(ConfigurationError): conf.validate() def test_read(self): conf = AnacondaConfiguration() with tempfile.NamedTemporaryFile("w") as f: conf.read(f.name) self.assertEqual(len(conf.get_sources()), 1) self.assertEqual(conf.get_sources()[0], f.name) def test_default_read(self): AnacondaConfiguration.from_defaults() def test_write(self): conf = AnacondaConfiguration() with tempfile.NamedTemporaryFile("r+") as f: conf.write(f.name) f.flush() self.assertFalse(f.read(), "The file should be empty.") def test_default_write(self): conf = AnacondaConfiguration.from_defaults() with tempfile.NamedTemporaryFile("r+") as f: conf.write(f.name) f.flush() self.assertTrue(f.read(), "The file shouldn't be empty.") def test_set_from_files(self): conf = AnacondaConfiguration.from_defaults() paths = [] with tempfile.TemporaryDirectory() as d: # Add nonexistent file. nonexistent = os.path.join(d, "nonexistent") paths.append(nonexistent) # Add empty directory. empty_dir = os.path.join(d, "empty") os.mkdir(empty_dir) paths.append(empty_dir) # Add existing file. existing = os.path.join(d, "a.conf") paths.append(existing) with open(existing, mode="w") as f: f.write("") # Add non-empty directory. conf_dir = os.path.join(d, "conf.d") os.mkdir(conf_dir) paths.append(conf_dir) for name in ["b.conf", "c.conf", "d"]: with open(os.path.join(conf_dir, name), mode="w") as f: f.write("") # Check the paths. self.assertEqual([os.path.relpath(path, d) for path in paths], ["nonexistent", "empty", "a.conf", "conf.d"]) conf._sources = [] conf.set_from_files(paths) # Check the loaded files. self.assertEqual( [os.path.relpath(path, d) for path in conf.get_sources()], ["a.conf", "conf.d/b.conf", "conf.d/c.conf"]) def _check_configuration_sources(self, conf, file_names): """Check the loaded configuration sources.""" file_paths = [os.path.join(CONFIG_DIR, path) for path in file_names] self.assertEqual(file_paths, conf.get_sources()) @patch("pyanaconda.core.configuration.anaconda.ANACONDA_CONFIG_DIR", CONFIG_DIR) def test_set_from_requested_profile(self): conf = AnacondaConfiguration.from_defaults() # Test an unknown requested profile. with self.assertRaises(ConfigurationError) as cm: conf.set_from_profile("unknown-profile") expected = "Unable to find any suitable configuration files " \ "for the 'unknown-profile' profile." self.assertEqual(str(cm.exception), expected) # Test a known requested profile. conf.set_from_profile("fedora-workstation") self._check_configuration_sources(conf, [ "anaconda.conf", "profile.d/fedora.conf", "profile.d/fedora-workstation.conf" ]) @patch("pyanaconda.core.configuration.anaconda.ANACONDA_CONFIG_DIR", CONFIG_DIR) def test_set_from_detected_profile(self): conf = AnacondaConfiguration.from_defaults() # Test unknown os-release values. with self.assertLogs(level="WARNING") as cm: conf.set_from_detected_profile("unknown-os", "unknown-variant") expected = \ "Unable to find any suitable configuration files for the detected " \ "os-release values. No profile configuration will be used." self.assertIn(expected, "\n".join(cm.output)) # Test known os-release values. conf.set_from_detected_profile("fedora", "workstation") self._check_configuration_sources(conf, [ "anaconda.conf", "profile.d/fedora.conf", "profile.d/fedora-workstation.conf" ]) def _check_pattern(self, pattern): """Check the specified module pattern.""" if pattern.endswith(".*"): self.assertIn(pattern[:-2], self.MODULE_NAMESPACES) else: self.assertIn(pattern, self.MODULE_NAMES) def test_activatable_modules(self): """Test the activatable_modules option.""" conf = AnacondaConfiguration.from_defaults() for pattern in conf.anaconda.activatable_modules: self._check_pattern(pattern) def test_kickstart_modules(self): """Test the kickstart_modules option.""" conf = AnacondaConfiguration.from_defaults() self.assertEqual(conf.anaconda.activatable_modules, [ "org.fedoraproject.Anaconda.Modules.*", "org.fedoraproject.Anaconda.Addons.*" ]) parser = conf.get_parser() parser.read_string( dedent(""" [Anaconda] kickstart_modules = org.fedoraproject.Anaconda.Modules.Timezone org.fedoraproject.Anaconda.Modules.Localization org.fedoraproject.Anaconda.Modules.Security """)) self.assertEqual(conf.anaconda.activatable_modules, [ "org.fedoraproject.Anaconda.Modules.Timezone", "org.fedoraproject.Anaconda.Modules.Localization", "org.fedoraproject.Anaconda.Modules.Security", "org.fedoraproject.Anaconda.Addons.*" ]) for pattern in conf.anaconda.activatable_modules: self._check_pattern(pattern) def test_forbidden_modules(self): """Test the forbidden_modules option.""" conf = AnacondaConfiguration.from_defaults() for pattern in conf.anaconda.forbidden_modules: self._check_pattern(pattern) def test_addons_enabled_modules(self): """Test the addons_enabled option.""" conf = AnacondaConfiguration.from_defaults() self.assertEqual(conf.anaconda.forbidden_modules, []) parser = conf.get_parser() parser.read_string( dedent(""" [Anaconda] forbidden_modules = org.fedoraproject.Anaconda.Modules.Timezone org.fedoraproject.Anaconda.Modules.Localization org.fedoraproject.Anaconda.Modules.Security """)) self.assertEqual(conf.anaconda.forbidden_modules, [ "org.fedoraproject.Anaconda.Modules.Timezone", "org.fedoraproject.Anaconda.Modules.Localization", "org.fedoraproject.Anaconda.Modules.Security", ]) parser.read_string( dedent(""" [Anaconda] addons_enabled = True """)) self.assertEqual(conf.anaconda.forbidden_modules, [ "org.fedoraproject.Anaconda.Modules.Timezone", "org.fedoraproject.Anaconda.Modules.Localization", "org.fedoraproject.Anaconda.Modules.Security", ]) parser.read_string( dedent(""" [Anaconda] addons_enabled = False """)) self.assertEqual(conf.anaconda.forbidden_modules, [ "org.fedoraproject.Anaconda.Addons.*", "org.fedoraproject.Anaconda.Modules.Timezone", "org.fedoraproject.Anaconda.Modules.Localization", "org.fedoraproject.Anaconda.Modules.Security", ]) for pattern in conf.anaconda.forbidden_modules: self._check_pattern(pattern) def test_optional_modules(self): """Test the optional_modules option.""" conf = AnacondaConfiguration.from_defaults() for pattern in conf.anaconda.optional_modules: self._check_pattern(pattern) def test_bootloader(self): conf = AnacondaConfiguration.from_defaults() self.assertIn("selinux", conf.bootloader.preserved_arguments) def test_default_partitioning(self): conf = AnacondaConfiguration.from_defaults() self.assertEqual(conf.storage.default_partitioning, [{ 'name': '/', 'min': Size("1024 MiB"), 'max': Size("70 GiB"), }, { 'name': '/home', 'min': Size("500 MiB"), 'free': Size("50 GiB"), }]) def test_convert_partitioning(self): convert_line = StorageSection._convert_partitioning_line self.assertEqual( convert_line("/ (min 1 GiB, max 2 GiB, free 20 GiB)"), { "name": "/", "min": Size("1 GiB"), "max": Size("2 GiB"), "free": Size("20 GiB") }) self.assertEqual(convert_line("/home (size 1 GiB)"), { "name": "/home", "size": Size("1 GiB") }) self.assertEqual(convert_line("swap"), {"name": "swap"}) with self.assertRaises(ValueError): convert_line("") with self.assertRaises(ValueError): convert_line("(size 1 GiB)") with self.assertRaises(ValueError): convert_line("/home (size)") with self.assertRaises(ValueError): convert_line("/home (invalid 1 GiB)") with self.assertRaises(ValueError): convert_line("/home (size 1 GiB, min 2 GiB)") with self.assertRaises(ValueError): convert_line("/home (max 2 GiB)") def test_default_installation_source(self): conf = AnacondaConfiguration.from_defaults() self.assertEqual(conf.payload.default_source, SOURCE_TYPE_CLOSEST_MIRROR) def test_default_password_policies(self): conf = AnacondaConfiguration.from_defaults() self.assertEqual(conf.ui.password_policies, [ { 'name': 'root', "quality": 1, "length": 6, }, { 'name': 'user', "quality": 1, "length": 6, "empty": True, }, { 'name': 'luks', "quality": 1, "length": 6, }, ]) def test_convert_password_policy(self): convert_line = UserInterfaceSection._convert_policy_line self.assertEqual( convert_line("root (quality 100, length 10, empty, strict)"), { "name": "root", "quality": 100, "length": 10, "empty": True, "strict": True, }) self.assertEqual(convert_line("luks (quality 100, length 10)"), { "name": "luks", "quality": 100, "length": 10, }) with self.assertRaises(ValueError): convert_line("") with self.assertRaises(ValueError): convert_line("(empty)") with self.assertRaises(ValueError): convert_line("user (quality)") with self.assertRaises(ValueError): convert_line("user (invalid 100)") # Missing length. with self.assertRaises(ValueError): convert_line("user (quality 100)") # Missing quality. with self.assertRaises(ValueError): convert_line("user (length 10)")
def get_name(self, exception_type): """Get a DBus name for the given exception type.""" return get_dbus_name(*self._default_namespace, exception_type.__name__)