def test_match_path_arch_ppc64le(self): method = UEFIAMD64BootMethod() backend = random.choice(["http", "tftp"]) self.assertEqual( {"arch": "ppc64el"}, method.match_path(backend, b"/grub/grub.cfg-default-ppc64le"), )
def test_match_path_arch_x86_64(self): method = UEFIAMD64BootMethod() backend = random.choice(["http", "tftp"]) self.assertEqual( {"arch": "amd64"}, method.match_path(backend, b"/grub/grub.cfg-default-x86_64"), )
def test_link_bootloader_logs_missing_bootloader_files(self): method = UEFIAMD64BootMethod() self.patch(grub_module.os.path, "exists").return_value = False mock_maaslog = self.patch(grub_module.maaslog, "error") bootloader_dir = "/var/lib/maas/boot-resources/%s" % factory.make_name( "snapshot") method._find_and_copy_bootloaders(bootloader_dir) self.assertThat(mock_maaslog, MockCalledOnce())
def test_match_path_mac_dash(self): method = UEFIAMD64BootMethod() backend = random.choice(["http", "tftp"]) mac = factory.make_mac_address().replace(":", "-") self.assertEqual( {"mac": mac}, method.match_path(backend, f"/grub/grub.cfg-{mac}".encode()), )
def test_match_path_arch(self): method = UEFIAMD64BootMethod() backend = random.choice(["http", "tftp"]) arch = factory.make_string() self.assertEqual( {"arch": arch}, method.match_path(backend, f"/grub/grub.cfg-default-{arch}".encode()), )
def test_get_reader_tftp(self): # Given the right configuration options, the UEFI configuration is # correctly rendered. method = UEFIAMD64BootMethod() params = make_kernel_parameters(arch="amd64", purpose="xinstall") fs_host = "(http,%s:5248)/images" % (convert_host_to_uri_str( params.fs_host)) output = method.get_reader(backend=None, kernel_params=params, protocol="tftp") # The output is a BytesReader. self.assertThat(output, IsInstance(BytesReader)) output = output.read(10000).decode("utf-8") # The template has rendered without error. UEFI configurations # typically start with a DEFAULT line. self.assertThat(output, StartsWith('set default="0"')) # The UEFI parameters are all set according to the options. image_dir = compose_image_path( osystem=params.osystem, arch=params.arch, subarch=params.subarch, release=params.release, label=params.label, ) self.assertThat( output, MatchesAll( MatchesRegex( r".*\s+lin.*cc:\\{\'datasource_list\':" r" \[\'MAAS\'\]\\}end_cc.*", re.MULTILINE | re.DOTALL, ), MatchesRegex( r".*^\s+linux %s/%s/%s .+?$" % ( re.escape(fs_host), re.escape(image_dir), params.kernel, ), re.MULTILINE | re.DOTALL, ), MatchesRegex( r".*^\s+initrd %s/%s/%s$" % ( re.escape(fs_host), re.escape(image_dir), params.initrd, ), re.MULTILINE | re.DOTALL, ), ), )
def test_link_bootloader_copies_previous_downloaded_files(self): method = UEFIAMD64BootMethod() with tempdir() as tmp: new_dir = os.path.join(tmp, "new") current_dir = os.path.join(tmp, "current") os.makedirs(new_dir) os.makedirs(current_dir) for bootloader_file in method.bootloader_files: factory.make_file(current_dir, bootloader_file) method.link_bootloader(new_dir) for bootloader_file in method.bootloader_files: bootloader_file_path = os.path.join(new_dir, bootloader_file) self.assertTrue(os.path.isfile(bootloader_file_path))
def test_get_reader_with_local_purpose(self): # If purpose is "local", the config.localboot.template should be # used. method = UEFIAMD64BootMethod() options = { "backend": None, "kernel_params": make_kernel_parameters(purpose="local", arch="amd64"), "protocol": random.choice(["tftp", "http"]), } output = method.get_reader(**options).read(10000).decode("utf-8") self.assertIn("chainloader /efi/", output) self.assertIn("bootx64.efi", output) self.assertIn("shimx64.efi", output) self.assertIn("grubx64.efi", output)
def test_get_reader_with_extra_arguments_does_not_affect_output(self): # get_reader() allows any keyword arguments as a safety valve. method = UEFIAMD64BootMethod() options = { "backend": None, "kernel_params": make_kernel_parameters(purpose="xinstall"), "protocol": random.choice(["tftp", "http"]), } # Capture the output before sprinking in some random options. output_before = method.get_reader(**options).read(10000) # Sprinkle some magic in. options.update((factory.make_name("name"), factory.make_name("value")) for _ in range(10)) # Capture the output after sprinking in some random options. output_after = method.get_reader(**options).read(10000) # The generated template is the same. self.assertEqual(output_before, output_after)
def test_get_reader_with_commissioning_purpose(self): # If purpose is "commissioning", the config.commissioning.template # should be used. method = UEFIAMD64BootMethod() params = make_kernel_parameters(purpose="commissioning", arch="amd64") options = { "backend": None, "kernel_params": params, "protocol": random.choice(["tftp", "http"]), } output = method.get_reader(**options).read(10000).decode("utf-8") self.assertThat( output, ContainsAll([ "menuentry 'Ephemeral'", "%s/%s/%s" % (params.osystem, params.arch, params.subarch), params.kernel, ]), )
def test_link_bootloader_creates_grub_cfg(self): method = UEFIAMD64BootMethod() with tempdir() as tmp: stream_path = os.path.join( tmp, "bootloader", method.bios_boot_method, method.bootloader_arches[0], ) os.makedirs(stream_path) for bootloader_file in method.bootloader_files: factory.make_file(stream_path, bootloader_file) method.link_bootloader(tmp) for bootloader_file in method.bootloader_files: bootloader_file_path = os.path.join(tmp, bootloader_file) self.assertTrue(os.path.islink(bootloader_file_path)) grub_file_path = os.path.join(tmp, "grub", "grub.cfg") self.assertTrue(grub_file_path, FileContains(CONFIG_FILE))
def test_link_bootloader_copies_from_system(self): method = UEFIAMD64BootMethod() bootloader_dir = "/var/lib/maas/boot-resources/%s" % factory.make_name( "snapshot") # Since the fall back looks for paths on the filesystem we need to # intercept the calls and make sure they were called with the right # arguments otherwise the test environment will interfere. allowed_src_files = [ "/usr/lib/shim/shim.efi.signed", "/usr/lib/grub/x86_64-efi-signed/grubnetx64.efi.signed", ] def fake_exists(path): if path in allowed_src_files: return True else: return False self.patch(grub_module.os.path, "exists").side_effect = fake_exists mock_atomic_symlink = self.patch(grub_module, "atomic_symlink") method._find_and_copy_bootloaders(bootloader_dir) self.assertThat( mock_atomic_symlink, MockAnyCall( "/usr/lib/shim/shim.efi.signed", os.path.join(bootloader_dir, "bootx64.efi"), ), ) self.assertThat( mock_atomic_symlink, MockAnyCall( "/usr/lib/grub/x86_64-efi-signed/grubnetx64.efi.signed", os.path.join(bootloader_dir, "grubx64.efi"), ), )
UEFIAMD64BootMethod, UEFIAMD64HTTPBootMethod, UEFIEBCBootMethod, UEFIARM64BootMethod, UEFIARM64HTTPBootMethod, OpenFirmwarePPC64ELBootMethod, ) from provisioningserver.boot.powernv import ( # noqa:E402 isort:skip PowerNVBootMethod, ) from provisioningserver.boot.pxe import PXEBootMethod # noqa:E402 isort:skip from provisioningserver.boot.s390x import ( # noqa:E402 isort:skip S390XBootMethod, ) from provisioningserver.boot.s390x_partition import ( # noqa:E402 isort:skip S390XPartitionBootMethod, ) from provisioningserver.boot.windows import ( # noqa:E402 isort:skip WindowsPXEBootMethod, ) builtin_boot_methods = [ IPXEBootMethod(), PXEBootMethod(), UEFIAMD64BootMethod(), UEFIAMD64HTTPBootMethod(), UEFIEBCBootMethod(), UEFIARM64BootMethod(), UEFIARM64HTTPBootMethod(), OpenFirmwarePPC64ELBootMethod(), PowerNVBootMethod(), WindowsPXEBootMethod(), S390XBootMethod(), S390XPartitionBootMethod(), ] for method in builtin_boot_methods: BootMethodRegistry.register_item(method.name, method)
def test_match_path_none(self): method = UEFIAMD64BootMethod() backend = random.choice(["http", "tftp"]) self.assertIsNone( method.match_path(backend, factory.make_string().encode()))