Ejemplo n.º 1
0
    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"])
Ejemplo n.º 2
0
    def test_get_reader(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)
        # 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+linuxefi  %s/%s/%s .+?$' %
                    (re.escape(fs_host), re.escape(image_dir), params.kernel),
                    re.MULTILINE | re.DOTALL),
                MatchesRegex(
                    r'.*^\s+initrdefi %s/%s/%s$' %
                    (re.escape(fs_host), re.escape(image_dir), params.initrd),
                    re.MULTILINE | re.DOTALL)))
Ejemplo n.º 3
0
 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)))
Ejemplo n.º 4
0
 def test_get_reader_ephemeral(self):
     # Given the right configuration options, the iPXE configuration is
     # correctly rendered.
     method = IPXEBootMethod()
     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,
     )
     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. iPXE configurations
     # start with #ipxe.
     self.assertThat(output, StartsWith("#!ipxe"))
     # The iPXE 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\s+" % (
                     re.escape(fs_host),
                     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),
         ),
     )
Ejemplo n.º 5
0
 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)
Ejemplo n.º 6
0
 def test_get_reader_install(self):
     # Given the right configuration options, the PXE configuration is
     # correctly rendered.
     method = IPXEBootMethod()
     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. iPXE configurations
     # start with #ipxe.
     self.assertThat(output, StartsWith("#!ipxe"))
     # The iPXE 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*imgargs .+?$", re.MULTILINE | re.DOTALL),
         ),
     )
Ejemplo n.º 7
0
    def get_reader(self, backend, kernel_params, protocol, **extra):
        """Render a configuration file as a unicode string.

        :param backend: requesting backend
        :param kernel_params: An instance of `KernelParameters`.
        :param protocol: The protocol the transfer is happening over.
        :param extra: Allow for other arguments. This is a safety valve;
            parameters generated in another component (for example, see
            `TFTPBackend.get_boot_method_reader`) won't cause this to break.
        """
        def kernel_command(params):
            """Return the kernel command, adjusted for UEFI to work.

            See the similar function in BootMethod, and the callsite below.

            The issue here is that grub throws a fit when the braces on
            cc:{...}end_cc are hit, for whatever reason.  Escape _JUST_ those.
            """
            return re.sub(
                r"cc:{(?P<inner>[^}]*)}end_cc",
                r"cc:\{\g<inner>\}end_cc",
                compose_kernel_command_line(params),
            )

        template = self.get_template(kernel_params.purpose, kernel_params.arch,
                                     kernel_params.subarch)
        namespace = self.compose_template_namespace(kernel_params)

        # TFTP is much slower than HTTP. If GRUB was transfered over TFTP use
        # GRUBs internal HTTP implementation to download the kernel and initrd.
        # If HTTP or HTTPS was used don't specify host to continue to use the
        # UEFI firmware's internal HTTP implementation.
        if protocol == "tftp":
            namespace["fs_efihost"] = "(http,%s:5248)/images/" % (
                convert_host_to_uri_str(kernel_params.fs_host))
        else:
            namespace["fs_efihost"] = "/images/"

        # Bug#1651452 - kernel command needs some extra escapes, but ONLY for
        # UEFI.  And so we fix it here, instead of in the common code.  See
        # also src/provisioningserver/kernel_opts.py.
        namespace["kernel_command"] = kernel_command
        return BytesReader(
            template.substitute(namespace).strip().encode("utf-8"))
Ejemplo n.º 8
0
 def fs_efihost(params):
     return "(http,%s:5248)/images/" % (
         convert_host_to_uri_str(params.fs_host)
     )
Ejemplo n.º 9
0
 def fs_host(params):
     return "http://%s:5248/images/" % (
         convert_host_to_uri_str(params.fs_host)
     )
Ejemplo n.º 10
0
 def fs_host(params):
     return convert_host_to_uri_str(params.fs_host)