def test_get_reader_scenarios(self): method = PXEBootMethod() get_ephemeral_name = self.patch(kernel_opts, "get_ephemeral_name") get_ephemeral_name.return_value = factory.make_name("ephemeral") osystem = factory.make_name('osystem') arch = factory.make_name('arch') subarch = factory.make_name('subarch') options = { "backend": None, "kernel_params": make_kernel_parameters(testcase=self, osystem=osystem, subarch=subarch, arch=arch, purpose=self.purpose), } fs_host = 'http://%s:5248/images' % (convert_host_to_uri_str( options['kernel_params'].fs_host)) output = method.get_reader(**options).read(10000).decode("utf-8") config = parse_pxe_config(output) # The default section is defined. default_section_label = config.header["DEFAULT"] self.assertThat(config, Contains(default_section_label)) default_section = dict(config[default_section_label]) contains_arch_path = StartsWith("%s/%s/%s/%s" % (fs_host, osystem, arch, subarch)) self.assertThat(default_section["KERNEL"], contains_arch_path) self.assertThat(default_section["INITRD"], contains_arch_path) self.assertEqual("2", default_section["IPAPPEND"])
def test_get_reader_with_extra_arguments_does_not_affect_output(self): # get_reader() allows any keyword arguments as a safety valve. method = PXEBootMethod() options = { "backend": None, "kernel_params": make_kernel_parameters(self, purpose="install"), } # 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_install(self): # Given the right configuration options, the PXE configuration is # correctly rendered. method = PXEBootMethod() params = make_kernel_parameters(self, 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) # The output is a BytesReader. self.assertThat(output, IsInstance(BytesReader)) output = output.read(10000).decode("utf-8") # The template has rendered without error. PXELINUX configurations # typically start with a DEFAULT line. self.assertThat(output, StartsWith("DEFAULT ")) # The PXE 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+KERNEL %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), MatchesRegex(r'.*^\s+APPEND .+?$', re.MULTILINE | re.DOTALL)))
def test_get_reader_with_local_purpose(self): # If purpose is "local", the config.localboot.template should be # used. method = PXEBootMethod() options = { "backend": None, "kernel_params": make_kernel_parameters(purpose="local"), } output = method.get_reader(**options).read(10000) self.assertIn(b"LOCALBOOT 0", output)
def test_get_reader_with_local_purpose_amd64_arch(self): # Intel amd64 is a special case and needs to use the chain.c32 # loader as the LOCALBOOT PXE directive is unreliable. method = PXEBootMethod() options = { "backend": None, "kernel_params": make_kernel_parameters(arch="amd64", purpose="local"), } output = method.get_reader(**options).read(10000) self.assertIn(b"chain.c32", output) self.assertNotIn(b"LOCALBOOT", output)
def test_get_reader_ephemeral(self): # Given the right configuration options, the PXE configuration is # correctly rendered. method = PXEBootMethod() xtra = ( "custom_xtra_cfg=http://{{ kernel_params.fs_host }}/" "my_extra_config?mac={{ kernel_params.mac }}" ) params = make_kernel_parameters( self, arch="amd64", subarch="generic", purpose="ephemeral", extra_opts=xtra, ) output = method.get_reader(backend=None, kernel_params=params) # The output is a BytesReader. self.assertThat(output, IsInstance(BytesReader)) output = output.read(10000).decode("utf-8") # The template has rendered without error. PXELINUX configurations # typically start with a DEFAULT line. self.assertThat(output, StartsWith("DEFAULT ")) # The PXE 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+KERNEL %s/%s$" % (re.escape(image_dir), params.kernel), re.MULTILINE | re.DOTALL, ), MatchesRegex( r".*^\s+APPEND initrd=%s/%s\s+" % (re.escape(image_dir), params.initrd), re.MULTILINE | re.DOTALL, ), MatchesRegex( r".*\s+custom_xtra_cfg=http://%s/my_extra_config.*?\s+" % (params.fs_host), re.MULTILINE | re.DOTALL, ), MatchesRegex(r".*\s+maas_url=.+?$", re.MULTILINE | re.DOTALL), ), )
def test_get_reader_xinstall_mustang_dtb(self): # Architecture specific test. # Given the right configuration options, the PXE configuration is # correctly rendered for Mustang. method = PXEBootMethod() params = make_kernel_parameters( testcase=self, osystem="ubuntu", arch="arm64", subarch="xgene-uboot-mustang", purpose="xinstall", ) output = method.get_reader(backend=None, kernel_params=params) # The output is a BytesReader. self.assertThat(output, IsInstance(BytesReader)) output = output.read(10000).decode("utf-8") # The template has rendered without error. PXELINUX configurations # typically start with a DEFAULT line. self.assertThat(output, StartsWith("DEFAULT ")) # The PXE 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+KERNEL %s/%s$" % (re.escape(image_dir), params.kernel), re.MULTILINE | re.DOTALL, ), MatchesRegex( r".*^\s+INITRD %s/%s$" % (re.escape(image_dir), params.initrd), re.MULTILINE | re.DOTALL, ), MatchesRegex( r".*^\s+FDT %s/%s$" % (re.escape(image_dir), params.boot_dtb), re.MULTILINE | re.DOTALL, ), MatchesRegex(r".*^\s+APPEND .+?$", re.MULTILINE | re.DOTALL), ), )
def test_get_reader_scenarios(self): # The commissioning config uses an extra PXELINUX module to auto # select between i386 and amd64. method = PXEBootMethod() get_ephemeral_name = self.patch(kernel_opts, "get_ephemeral_name") get_ephemeral_name.return_value = factory.make_name("ephemeral") osystem = factory.make_name("osystem") options = { "backend": None, "kernel_params": make_kernel_parameters( testcase=self, osystem=osystem, subarch="generic", purpose="enlist", ), } fs_host = "http://%s:5248/images" % ( convert_host_to_uri_str(options["kernel_params"].fs_host) ) output = method.get_reader(**options).read(10000).decode("utf-8") config = parse_pxe_config(output) # The default section is defined. default_section_label = config.header["DEFAULT"] self.assertThat(config, Contains(default_section_label)) default_section = config[default_section_label] # The default section uses the ifcpu64 module, branching to the "i386" # or "amd64" labels accordingly. self.assertEqual("ifcpu64.c32", default_section["KERNEL"]) self.assertEqual( ["amd64", "--", "i386"], default_section["APPEND"].split() ) # Both "i386" and "amd64" sections exist. self.assertThat(config, ContainsAll(("i386", "amd64"))) # Each section defines KERNEL, INITRD, and APPEND settings. The # KERNEL and INITRD ones contain paths referring to their # architectures. for section_label in ("i386", "amd64"): section = config[section_label] self.assertThat( section, ContainsAll(("KERNEL", "INITRD", "APPEND")) ) contains_arch_path = StartsWith( "%s/%s/%s/" % (fs_host, osystem, section_label) ) self.assertThat(section["KERNEL"], contains_arch_path) self.assertThat(section["INITRD"], contains_arch_path) self.assertIn("APPEND", section)