コード例 #1
0
ファイル: netboot.py プロジェクト: holmesb/cobbler
    def _generate_netboot_profile(self, profile, cfglines: List[str]):
        """
        Generates the ISOLINUX cfg configuration for any profiles included in the image.
        :param profile: The profile which the configuration should be generated for.
        :param cfglines: The already existing lines of the configuration.
        """
        self.logger.info('Processing profile: "%s"', profile.name)
        dist = profile.get_conceptual_parent()
        distname = self.make_shorter(dist.name)
        self.copy_boot_files(dist, self.isolinuxdir, distname)

        cfglines.append("")
        cfglines.append("LABEL %s" % profile.name)
        cfglines.append("  MENU LABEL %s" % profile.name)
        cfglines.append("  kernel %s.krn" % distname)

        data = utils.blender(self.api, False, profile)

        # SUSE is not using 'text'. Instead 'textmode' is used as kernel option.
        if dist is not None:
            utils.kopts_overwrite(data["kernel_options"],
                                  self.api.settings().server, dist.breed)

        if not re.match(r"[a-z]+://.*", data["autoinstall"]):
            data[
                "autoinstall"] = "http://%s:%s/cblr/svc/op/autoinstall/profile/%s" % (
                    data["server"],
                    data["http_port"],
                    profile.name,
                )

        append_builder = AppendLineBuilder(distro_name=distname, data=data)
        append_line = append_builder.generate_profile(dist.breed)
        cfglines.append(append_line)
コード例 #2
0
ファイル: utils_test.py プロジェクト: openSUSE/cobbler
def test_kopts_overwrite():
    # Arrange
    distro_breed = "suse"
    system_name = "kopts_test_system"
    kopts = {"textmode": False, "text": True}

    # Act
    utils.kopts_overwrite(kopts, "servername", distro_breed, system_name)

    # Assert
    assert "textmode" in kopts
    assert "info" in kopts
コード例 #3
0
    def _generate_descendant(
        self,
        descendant,
        cfglines: List[str],
        distro,
        airgapped: bool,
        repo_names_to_copy: dict,
    ):
        """
        Generate the ISOLINUX cfg configuration file for the descendant.
        :param descendant: The descendant to generate the config file for. Must be a profile or system object.
        :param cfglines: The content of the file which has already been generated.
        :param distro: The parent distro.
        :param airgapped: Whether the generated ISO should be bootable in an airgapped environment or not.
        :param repo_names_to_copy: The repository names to copy in the case of an airgapped environment.
        """
        menu_indent = 0
        if descendant.COLLECTION_TYPE == "system":
            menu_indent = 4

        data = utils.blender(self.api, False, descendant)

        # SUSE is not using 'text'. Instead 'textmode' is used as kernel option.
        if distro is not None:
            utils.kopts_overwrite(data["kernel_options"],
                                  self.api.settings().server, distro.breed)

        cfglines.append("")
        cfglines.append("LABEL %s" % descendant.name)
        if menu_indent:
            cfglines.append("  MENU INDENT %d" % menu_indent)
        cfglines.append("  MENU LABEL %s" % descendant.name)
        cfglines.append("  kernel %s" % os.path.basename(distro.kernel))

        cfglines.append(
            _generate_append_line_standalone(data, distro, descendant))

        autoinstall_data = self._generate_autoinstall_data(
            descendant, distro, airgapped, data, repo_names_to_copy)
        autoinstall_name = os.path.join(self.isolinuxdir,
                                        "%s.cfg" % descendant.name)
        with open(autoinstall_name, "w+") as autoinstall_file:
            autoinstall_file.write(autoinstall_data)
コード例 #4
0
def test_kopts_overwrite():
    # Arrange
    test_api = CobblerAPI()
    test_manager = CollectionManager(test_api)
    test_distro = Distro(test_manager)
    test_distro.set_breed("suse")
    test_distro.name = "kopts_test_distro"
    test_profile = Profile(test_manager)
    test_profile.distro = test_distro.name
    test_system = System(test_manager)
    test_system.name = "kopts_test_system"
    kopts = {"textmode": False, "text": True}

    # Act
    utils.kopts_overwrite(test_system, test_distro, kopts, test_api.settings())

    # Assert
    assert "textmode" in kopts
    assert "info" in kopts
コード例 #5
0
    def generate_standalone_iso(self, imagesdir, isolinuxdir, distname, filesource, airgapped: bool, profiles):
        """
        Create bootable CD image to be used for handsoff CD installtions

        :param imagesdir: Unused Parameter.
        :param isolinuxdir: The parent directory where the file isolinux.cfg is located at.
        :param distname: The name of the Cobbler distribution.
        :param filesource: Not clear what this exactly does
        :param airgapped: Whether the repositories have to be locally available or the internet is reachable.
        :param profiles: The list of profiles to include.
        """
        # Get the distro object for the requested distro and then get all of its descendants (profiles/sub-profiles/
        # systems) with sort=True for profile/system heirarchy to allow menu indenting
        distro = self.api.find_distro(distname)
        if distro is None:
            utils.die("distro %s was not found, aborting" % distname)
        descendants = distro.get_descendants(sort=True)
        profiles = utils.input_string_or_list(profiles)

        if filesource is None:
            # Try to determine the source from the distro kernel path
            self.logger.debug("trying to locate source for distro")
            found_source = False
            (source_head, source_tail) = os.path.split(distro.kernel)
            while source_tail != '':
                if source_head == os.path.join(self.api.settings().webdir, "distro_mirror"):
                    filesource = os.path.join(source_head, source_tail)
                    found_source = True
                    self.logger.debug("found source in %s" % filesource)
                    break
                (source_head, source_tail) = os.path.split(source_head)
            # Can't find the source, raise an error
            if not found_source:
                utils.die("Error, no installation source found. When building a standalone ISO, you must specify a "
                          "--source if the distro install tree is not hosted locally")

        self.logger.info("copying kernels and initrds for standalone distro")
        self.copy_boot_files(distro, isolinuxdir, None)

        self.logger.info("generating an isolinux.cfg")
        isolinuxcfg = os.path.join(isolinuxdir, "isolinux.cfg")
        cfg = open(isolinuxcfg, "w+")
        cfg.write(self.iso_template)

        if airgapped:
            repo_names_to_copy = {}

        for descendant in descendants:
            # if a list of profiles was given, skip any others and their systems
            if profiles and ((descendant.COLLECTION_TYPE == 'profile' and descendant.name not in profiles)
                             or (descendant.COLLECTION_TYPE == 'system' and descendant.profile not in profiles)):
                continue

            menu_indent = 0
            if descendant.COLLECTION_TYPE == 'system':
                menu_indent = 4

            data = utils.blender(self.api, False, descendant)

            # SUSE is not using 'text'. Instead 'textmode' is used as kernel option.
            if distro is not None:
                utils.kopts_overwrite(data['kernel_options'], self.settings.server, distro.breed)

            cfg.write("\n")
            cfg.write("LABEL %s\n" % descendant.name)
            if menu_indent:
                cfg.write("  MENU INDENT %d\n" % menu_indent)
            cfg.write("  MENU LABEL %s\n" % descendant.name)
            cfg.write("  kernel %s\n" % os.path.basename(distro.kernel))

            append_line = "  append initrd=%s" % os.path.basename(distro.initrd)
            if distro.breed == "redhat":
                append_line += " inst.ks=cdrom:/isolinux/%s.cfg" % descendant.name
            if distro.breed == "suse":
                append_line += " autoyast=file:///isolinux/%s.cfg install=cdrom:///" % descendant.name
                if "install" in data["kernel_options"]:
                    del data["kernel_options"]["install"]
            if distro.breed in ["ubuntu", "debian"]:
                append_line += " auto-install/enable=true preseed/file=/cdrom/isolinux/%s.cfg" % descendant.name

            # add remaining kernel_options to append_line
            append_line += self.add_remaining_kopts(data["kernel_options"])
            cfg.write(append_line)

            if descendant.COLLECTION_TYPE == 'profile':
                autoinstall_data = self.api.autoinstallgen.generate_autoinstall_for_profile(descendant.name)
            elif descendant.COLLECTION_TYPE == 'system':
                autoinstall_data = self.api.autoinstallgen.generate_autoinstall_for_system(descendant.name)

            if distro.breed == "redhat":
                cdregex = re.compile(r"^\s*url .*\n", re.IGNORECASE | re.MULTILINE)
                autoinstall_data = cdregex.sub("cdrom\n", autoinstall_data, count=1)

            if airgapped:
                descendant_repos = data['repos']
                for repo_name in descendant_repos:
                    repo_obj = self.api.find_repo(repo_name)
                    error_fmt = (descendant.COLLECTION_TYPE + " " + descendant.name + " refers to repo " + repo_name
                                 + ", which %%s; cannot build airgapped ISO")

                    if repo_obj is None:
                        utils.die(error_fmt % "does not exist")
                    if not repo_obj.mirror_locally:
                        utils.die(error_fmt % "is not configured for local mirroring")
                    # FIXME: don't hardcode
                    mirrordir = os.path.join(self.settings.webdir, "repo_mirror", repo_obj.name)
                    if not os.path.exists(mirrordir):
                        utils.die(error_fmt % "has a missing local mirror directory")

                    repo_names_to_copy[repo_obj.name] = mirrordir

                    # update the baseurl in autoinstall_data to use the cdrom copy of this repo
                    reporegex = re.compile(r"^(\s*repo --name=" + repo_obj.name + " --baseurl=).*", re.MULTILINE)
                    autoinstall_data = reporegex.sub(r"\1" + "file:///mnt/source/repo_mirror/" + repo_obj.name,
                                                     autoinstall_data)

                # rewrite any split-tree repos, such as in redhat, to use cdrom
                srcreporegex = re.compile(r"^(\s*repo --name=\S+ --baseurl=).*/cobbler/distro_mirror/" + distro.name
                                          + r"/?(.*)", re.MULTILINE)
                autoinstall_data = srcreporegex.sub(r"\1" + "file:///mnt/source" + r"\2", autoinstall_data)

            autoinstall_name = os.path.join(isolinuxdir, "%s.cfg" % descendant.name)
            with open(autoinstall_name, "w+") as autoinstall_file:
                autoinstall_file.write(autoinstall_data)

        self.logger.info("done writing config")
        cfg.write("\n")
        cfg.write("MENU END\n")
        cfg.close()

        if airgapped:
            # copy any repos found in profiles or systems to the iso build
            repodir = os.path.abspath(os.path.join(isolinuxdir, "..", "repo_mirror"))
            if not os.path.exists(repodir):
                os.makedirs(repodir)

            for repo_name in repo_names_to_copy:
                src = repo_names_to_copy[repo_name]
                dst = os.path.join(repodir, repo_name)
                self.logger.info(" - copying repo '" + repo_name + "' for airgapped ISO")

                ok = utils.rsync_files(src, dst, "--exclude=TRANS.TBL --exclude=cache/ --no-g",
                                       quiet=True)
                if not ok:
                    utils.die("rsync of repo '" + repo_name + "' failed")

        # copy distro files last, since they take the most time
        cmd = "rsync -rlptgu --exclude=boot.cat --exclude=TRANS.TBL --exclude=isolinux/ %s/ %s/../"\
              % (filesource, isolinuxdir)
        self.logger.info("- copying distro %s files (%s)" % (distname, cmd))
        rc = utils.subprocess_call(cmd, shell=True)
        if rc:
            utils.die("rsync of distro files failed")
コード例 #6
0
    def generate_netboot_iso(self, imagesdir, isolinuxdir, profiles=None, systems=None,
                             exclude_dns: Optional[bool] = None):
        """
        Create bootable CD image to be used for network installations

        :param imagesdir: Currently unused parameter.
        :param isolinuxdir: The parent directory where the isolinux.cfg is located.
        :param profiles: The filter to generate a netboot iso for. You may specify multiple profiles on the CLI space
                        separated.
        :param systems: The filter to generate a netboot iso for. You may specify multiple systems on the CLI space
                        separated.
        :param exclude_dns: If this is True then the dns server is skipped. None or False will set it.
        """
        which_profiles = self.filter_systems_or_profiles(profiles, 'profile')
        which_systems = self.filter_systems_or_profiles(systems, 'system')

        # setup isolinux.cfg
        isolinuxcfg = os.path.join(isolinuxdir, "isolinux.cfg")
        cfg = open(isolinuxcfg, "w+")
        cfg.write(self.iso_template)

        # iterate through selected profiles
        for profile in which_profiles:
            self.logger.info("processing profile: %s" % profile.name)
            dist = profile.get_conceptual_parent()
            distname = self.make_shorter(dist.name)
            self.copy_boot_files(dist, isolinuxdir, distname)

            cfg.write("\n")
            cfg.write("LABEL %s\n" % profile.name)
            cfg.write("  MENU LABEL %s\n" % profile.name)
            cfg.write("  kernel %s.krn\n" % distname)

            data = utils.blender(self.api, False, profile)

            # SUSE is not using 'text'. Instead 'textmode' is used as kernel option.
            if dist is not None:
                utils.kopts_overwrite(data['kernel_options'], self.api.settings().server, dist.breed)

            if not re.match(r"[a-z]+://.*", data["autoinstall"]):
                data["autoinstall"] = "http://%s:%s/cblr/svc/op/autoinstall/profile/%s" % (
                    data["server"], self.api.settings().http_port, profile.name
                )

            append_line = " append initrd=%s.img" % distname
            if dist.breed == "suse":
                if "proxy" in data and data["proxy"] != "":
                    append_line += " proxy=%s" % data["proxy"]
                if "install" in data["kernel_options"] and data["kernel_options"]["install"] != "":
                    v = data["kernel_options"]["install"]
                    if isinstance(v, list):
                        v = v[0]
                        append_line += " install=%s" % v
                    del data["kernel_options"]["install"]
                else:
                    append_line += " install=http://%s:%s/cblr/links/%s" % (
                        data["server"], self.api.settings().http_port, dist.name
                    )
                if "autoyast" in data["kernel_options"] and data["kernel_options"]["autoyast"] != "":
                    append_line += " autoyast=%s" % data["kernel_options"]["autoyast"]
                    del data["kernel_options"]["autoyast"]
                else:
                    append_line += " autoyast=%s" % data["autoinstall"]

            if dist.breed == "redhat":
                if "proxy" in data and data["proxy"] != "":
                    append_line += " proxy=%s http_proxy=%s" % (data["proxy"], data["proxy"])
                append_line += " inst.ks=%s" % data["autoinstall"]

            if dist.breed in ["ubuntu", "debian"]:
                append_line += " auto-install/enable=true url=%s" % data["autoinstall"]
                if "proxy" in data and data["proxy"] != "":
                    append_line += " mirror/http/proxy=%s" % data["proxy"]
            append_line += self.add_remaining_kopts(data["kernel_options"])
            cfg.write(append_line)

        cfg.write("\nMENU SEPARATOR\n")

        # iterate through all selected systems
        for system in which_systems:
            self.logger.info("processing system: %s" % system.name)
            profile = system.get_conceptual_parent()
            dist = profile.get_conceptual_parent()
            distname = self.make_shorter(dist.name)
            self.copy_boot_files(dist, isolinuxdir, distname)

            cfg.write("\n")
            cfg.write("LABEL %s\n" % system.name)
            cfg.write("  MENU LABEL %s\n" % system.name)
            cfg.write("  kernel %s.krn\n" % distname)

            data = utils.blender(self.api, False, system)
            if not re.match(r"[a-z]+://.*", data["autoinstall"]):
                data["autoinstall"] = "http://%s:%s/cblr/svc/op/autoinstall/system/%s" % (
                    data["server"], self.api.settings().http_port, system.name
                )

            append_line = " append initrd=%s.img" % distname
            if dist.breed == "suse":
                if "proxy" in data and data["proxy"] != "":
                    append_line += " proxy=%s" % data["proxy"]
                if "install" in data["kernel_options"] and data["kernel_options"]["install"] != "":
                    append_line += " install=%s" % data["kernel_options"]["install"]
                    del data["kernel_options"]["install"]
                else:
                    append_line += " install=http://%s:%s/cblr/links/%s" % (
                        data["server"], self.api.settings().http_port, dist.name
                    )
                if "autoyast" in data["kernel_options"] and data["kernel_options"]["autoyast"] != "":
                    append_line += " autoyast=%s" % data["kernel_options"]["autoyast"]
                    del data["kernel_options"]["autoyast"]
                else:
                    append_line += " autoyast=%s" % data["autoinstall"]

            if dist.breed == "redhat":
                if "proxy" in data and data["proxy"] != "":
                    append_line += " proxy=%s http_proxy=%s" % (data["proxy"], data["proxy"])
                append_line += " inst.ks=%s" % data["autoinstall"]

            if dist.breed in ["ubuntu", "debian"]:
                append_line += " auto-install/enable=true url=%s netcfg/disable_autoconfig=true" % data["autoinstall"]
                if "proxy" in data and data["proxy"] != "":
                    append_line += " mirror/http/proxy=%s" % data["proxy"]
                # hostname is required as a parameter, the one in the preseed is not respected
                my_domain = "local.lan"
                if system.hostname != "":
                    # if this is a FQDN, grab the first bit
                    my_hostname = system.hostname.split(".")[0]
                    _domain = system.hostname.split(".")[1:]
                    if _domain:
                        my_domain = ".".join(_domain)
                else:
                    my_hostname = system.name.split(".")[0]
                    _domain = system.name.split(".")[1:]
                    if _domain:
                        my_domain = ".".join(_domain)
                # At least for debian deployments configured for DHCP networking this values are not used, but
                # specifying here avoids questions
                append_line += " hostname=%s domain=%s" % (my_hostname, my_domain)
                # A similar issue exists with suite name, as installer requires the existence of "stable" in the dists
                # directory
                append_line += " suite=%s" % dist.os_version

            # Try to add static ip boot options to avoid DHCP (interface/ip/netmask/gw/dns)
            # Check for overrides first and clear them from kernel_options
            my_int = None
            my_ip = None
            my_mask = None
            my_gw = None
            my_dns = None
            if dist.breed in ["suse", "redhat"]:
                if "netmask" in data["kernel_options"] and data["kernel_options"]["netmask"] != "":
                    my_mask = data["kernel_options"]["netmask"]
                    del data["kernel_options"]["netmask"]
                if "gateway" in data["kernel_options"] and data["kernel_options"]["gateway"] != "":
                    my_gw = data["kernel_options"]["gateway"]
                    del data["kernel_options"]["gateway"]

            if dist.breed == "redhat":
                if "ksdevice" in data["kernel_options"] and data["kernel_options"]["ksdevice"] != "":
                    my_int = data["kernel_options"]["ksdevice"]
                    if my_int == "bootif":
                        my_int = None
                    del data["kernel_options"]["ksdevice"]
                if "ip" in data["kernel_options"] and data["kernel_options"]["ip"] != "":
                    my_ip = data["kernel_options"]["ip"]
                    del data["kernel_options"]["ip"]
                if "dns" in data["kernel_options"] and data["kernel_options"]["dns"] != "":
                    my_dns = data["kernel_options"]["dns"]
                    del data["kernel_options"]["dns"]

            if dist.breed == "suse":
                if "netdevice" in data["kernel_options"] and data["kernel_options"]["netdevice"] != "":
                    my_int = data["kernel_options"]["netdevice"]
                    del data["kernel_options"]["netdevice"]
                if "hostip" in data["kernel_options"] and data["kernel_options"]["hostip"] != "":
                    my_ip = data["kernel_options"]["hostip"]
                    del data["kernel_options"]["hostip"]
                if "nameserver" in data["kernel_options"] and data["kernel_options"]["nameserver"] != "":
                    my_dns = data["kernel_options"]["nameserver"]
                    del data["kernel_options"]["nameserver"]

            if dist.breed in ["ubuntu", "debian"]:
                if "netcfg/choose_interface" in data["kernel_options"] and data["kernel_options"]["netcfg/choose_interface"] != "":
                    my_int = data["kernel_options"]["netcfg/choose_interface"]
                    del data["kernel_options"]["netcfg/choose_interface"]
                if "netcfg/get_ipaddress" in data["kernel_options"] and data["kernel_options"]["netcfg/get_ipaddress"] != "":
                    my_ip = data["kernel_options"]["netcfg/get_ipaddress"]
                    del data["kernel_options"]["netcfg/get_ipaddress"]
                if "netcfg/get_netmask" in data["kernel_options"] and data["kernel_options"]["netcfg/get_netmask"] != "":
                    my_mask = data["kernel_options"]["netcfg/get_netmask"]
                    del data["kernel_options"]["netcfg/get_netmask"]
                if "netcfg/get_gateway" in data["kernel_options"] and data["kernel_options"]["netcfg/get_gateway"] != "":
                    my_gw = data["kernel_options"]["netcfg/get_gateway"]
                    del data["kernel_options"]["netcfg/get_gateway"]
                if "netcfg/get_nameservers" in data["kernel_options"] and data["kernel_options"]["netcfg/get_nameservers"] != "":
                    my_dns = data["kernel_options"]["netcfg/get_nameservers"]
                    del data["kernel_options"]["netcfg/get_nameservers"]

            # If no kernel_options overrides are present find the management interface do nothing when zero or multiple
            # management interfaces are found
            if my_int is None:
                mgmt_ints = []
                mgmt_ints_multi = []
                slave_ints = []
                if len(list(data["interfaces"].keys())) >= 1:
                    for (iname, idata) in list(data["interfaces"].items()):
                        if idata["management"] and idata["interface_type"] in ["bond", "bridge"]:
                            # bonded/bridged management interface
                            mgmt_ints_multi.append(iname)
                        if idata["management"] and idata["interface_type"] not in ["bond", "bridge", "bond_slave", "bridge_slave", "bonded_bridge_slave"]:
                            # single management interface
                            mgmt_ints.append(iname)

                if len(mgmt_ints_multi) == 1 and len(mgmt_ints) == 0:
                    # Bonded/bridged management interface, find a slave interface if eth0 is a slave use that (it's what
                    # people expect)
                    for (iname, idata) in list(data["interfaces"].items()):
                        if idata["interface_type"] in ["bond_slave", "bridge_slave", "bonded_bridge_slave"] and idata["interface_master"] == mgmt_ints_multi[0]:
                            slave_ints.append(iname)

                    if "eth0" in slave_ints:
                        my_int = "eth0"
                    else:
                        my_int = slave_ints[0]
                    # Set my_ip from the bonded/bridged interface here
                    my_ip = data["ip_address_" + data["interface_master_" + my_int]]
                    my_mask = data["netmask_" + data["interface_master_" + my_int]]

                if len(mgmt_ints) == 1 and len(mgmt_ints_multi) == 0:
                    # Single management interface
                    my_int = mgmt_ints[0]

            # Lookup tcp/ip configuration data
            if my_ip is None and my_int is not None:
                intip = "ip_address_" + my_int
                if intip in data and data[intip] != "":
                    my_ip = data["ip_address_" + my_int]

            if my_mask is None and my_int is not None:
                intmask = "netmask_" + my_int
                if intmask in data and data[intmask] != "":
                    my_mask = data["netmask_" + my_int]

            if my_gw is None:
                if "gateway" in data and data["gateway"] != "":
                    my_gw = data["gateway"]

            if my_dns is None:
                if "name_servers" in data and data["name_servers"] != "":
                    my_dns = data["name_servers"]

            # Add information to the append_line
            if my_int is not None:
                intmac = "mac_address_" + my_int
                if dist.breed == "suse":
                    if intmac in data and data[intmac] != "":
                        append_line += " netdevice=%s" % data["mac_address_" + my_int].lower()
                    else:
                        append_line += " netdevice=%s" % my_int
                if dist.breed == "redhat":
                    if intmac in data and data[intmac] != "":
                        append_line += " ksdevice=%s" % data["mac_address_" + my_int]
                    else:
                        append_line += " ksdevice=%s" % my_int
                if dist.breed in ["ubuntu", "debian"]:
                    append_line += " netcfg/choose_interface=%s" % my_int

            if my_ip is not None:
                if dist.breed == "suse":
                    append_line += " hostip=%s" % my_ip
                if dist.breed == "redhat":
                    append_line += " ip=%s" % my_ip
                if dist.breed in ["ubuntu", "debian"]:
                    append_line += " netcfg/get_ipaddress=%s" % my_ip

            if my_mask is not None:
                if dist.breed in ["suse", "redhat"]:
                    append_line += " netmask=%s" % my_mask
                if dist.breed in ["ubuntu", "debian"]:
                    append_line += " netcfg/get_netmask=%s" % my_mask

            if my_gw is not None:
                if dist.breed in ["suse", "redhat"]:
                    append_line += " gateway=%s" % my_gw
                if dist.breed in ["ubuntu", "debian"]:
                    append_line += " netcfg/get_gateway=%s" % my_gw

            if exclude_dns is None or my_dns is not None:
                if dist.breed == "suse":
                    if type(my_dns) == list:
                        append_line += " nameserver=%s" % ",".join(my_dns)
                    else:
                        append_line += " nameserver=%s" % my_dns
                if dist.breed == "redhat":
                    if type(my_dns) == list:
                        append_line += " dns=%s" % ",".join(my_dns)
                    else:
                        append_line += " dns=%s" % my_dns
                if dist.breed in ["ubuntu", "debian"]:
                    if type(my_dns) == list:
                        append_line += " netcfg/get_nameservers=%s" % ",".join(my_dns)
                    else:
                        append_line += " netcfg/get_nameservers=%s" % my_dns

            # Add remaining kernel_options to append_line
            append_line += self.add_remaining_kopts(data["kernel_options"])
            cfg.write(append_line)

        cfg.write("\n")
        cfg.write("MENU END\n")
        cfg.close()
コード例 #7
0
    def build_kernel_options(self, system, profile, distro, image, arch,
                             autoinstall_path):
        """
        Builds the full kernel options line.
        """

        management_interface = None
        if system is not None:
            blended = utils.blender(self.api, False, system)
            # find the first management interface
            try:
                for intf in list(system.interfaces.keys()):
                    if system.interfaces[intf]["management"]:
                        management_interface = intf
                        break
            except:
                # just skip this then
                pass
        elif profile is not None:
            blended = utils.blender(self.api, False, profile)
        else:
            blended = utils.blender(self.api, False, image)

        append_line = ""
        kopts = blended.get("kernel_options", dict())
        kopts = utils.revert_strip_none(kopts)

        # SUSE and other distro specific kernel additions or modificatins
        utils.kopts_overwrite(system, distro, kopts, self.settings)

        # since network needs to be configured again (it was already in netboot) when kernel boots
        # and we choose to do it dinamically, we need to set 'ksdevice' to one of
        # the interfaces' MAC addresses in ppc systems.
        # ksdevice=bootif is not useful in yaboot, as the "ipappend" line is a pxe feature.
        if system and arch and (arch == "ppc" or arch == "ppc64"):
            for intf in list(system.interfaces.keys()):
                # use first interface with defined IP and MAC, since these are required
                # fields in a DHCP entry
                mac_address = system.interfaces[intf]['mac_address']
                ip_address = system.interfaces[intf]['ip_address']
                if mac_address and ip_address:
                    kopts['BOOTIF'] = '01-' + mac_address
                    kopts['ksdevice'] = mac_address
                    break

        # support additional initrd= entries in kernel options.
        if "initrd" in kopts:
            append_line = ",%s" % kopts.pop("initrd")
        hkopts = utils.dict_to_string(kopts)
        append_line = "%s %s" % (append_line, hkopts)

        # automatic installation file path rewriting (get URLs for local files)
        if autoinstall_path:

            # FIXME: need to make shorter rewrite rules for these URLs

            try:
                ipaddress = socket.gethostbyname_ex(blended["http_server"])[2][0]
            except socket.gaierror:
                ipaddress = blended["http_server"]
            URL_REGEX = "[a-zA-Z]*://.*"
            local_autoinstall_file = not re.match(URL_REGEX, autoinstall_path)
            if local_autoinstall_file:
                if system is not None:
                    autoinstall_path = "http://%s/cblr/svc/op/autoinstall/system/%s" % (ipaddress, system.name)
                else:
                    autoinstall_path = "http://%s/cblr/svc/op/autoinstall/profile/%s" % (ipaddress, profile.name)

            if distro.breed is None or distro.breed == "redhat":

                append_line += " kssendmac"
                append_line = "%s ks=%s" % (append_line, autoinstall_path)
                gpxe = blended["enable_gpxe"]
                if gpxe:
                    append_line = append_line.replace('ksdevice=bootif', 'ksdevice=${net0/mac}')
            elif distro.breed == "suse":
                append_line = "%s autoyast=%s" % (append_line, autoinstall_path)
                if management_interface:
                    append_line += "netdevice=%s" % management_interface
            elif distro.breed == "debian" or distro.breed == "ubuntu":
                append_line = "%s auto-install/enable=true priority=critical netcfg/choose_interface=auto url=%s" % (append_line, autoinstall_path)
                if management_interface:
                    append_line += " netcfg/choose_interface=%s" % management_interface
            elif distro.breed == "freebsd":
                append_line = "%s ks=%s" % (append_line, autoinstall_path)

                # rework kernel options for debian distros
                translations = {'ksdevice': "interface", 'lang': "locale"}
                for k, v in list(translations.items()):
                    append_line = append_line.replace("%s=" % k, "%s=" % v)

                # interface=bootif causes a failure
                append_line = append_line.replace("interface=bootif", "")
            elif distro.breed == "vmware":
                if distro.os_version.find("esxi") != -1:
                    # ESXi is very picky, it's easier just to redo the
                    # entire append line here since
                    append_line = " ks=%s %s" % (autoinstall_path, hkopts)
                    # ESXi likes even fewer options, so we remove them too
                    append_line = append_line.replace("kssendmac", "")
                else:
                    append_line = "%s vmkopts=debugLogToSerial:1 mem=512M ks=%s" % \
                        (append_line, autoinstall_path)
                # interface=bootif causes a failure
                append_line = append_line.replace("ksdevice=bootif", "")
            elif distro.breed == "xen":
                if distro.os_version.find("xenserver620") != -1:
                    img_path = os.path.join("/images", distro.name)
                    append_line = "append %s/xen.gz dom0_max_vcpus=2 dom0_mem=752M com1=115200,8n1 console=com1,vga --- %s/vmlinuz xencons=hvc console=hvc0 console=tty0 install answerfile=%s --- %s/install.img" % (img_path, img_path, autoinstall_path, img_path)
                    return append_line
            elif distro.breed == "powerkvm":
                append_line += " kssendmac"
                append_line = "%s kvmp.inst.auto=%s" % (append_line, autoinstall_path)

        if distro is not None and (distro.breed in ["debian", "ubuntu"]):
            # Hostname is required as a parameter, the one in the preseed is
            # not respected, so calculate if we have one here.
            # We're trying: first part of FQDN in hostname field, then system
            # name, then profile name.
            # In Ubuntu, this is at least used for the volume group name when
            # using LVM.
            domain = "local.lan"
            if system is not None:
                if system.hostname is not None and system.hostname != "":
                    # If this is a FQDN, grab the first bit
                    hostname = system.hostname.split(".")[0]
                    _domain = system.hostname.split(".")[1:]
                    if _domain:
                        domain = ".".join(_domain)
                else:
                    hostname = system.name
            else:
                # ubuntu at the very least does not like having underscores
                # in the hostname.
                # FIXME: Really this should remove all characters that are
                # forbidden in hostnames
                hostname = profile.name.replace("_", "")

            # At least for debian deployments configured for DHCP networking
            # this values are not used, but specifying here avoids questions
            append_line = "%s hostname=%s" % (append_line, hostname)
            append_line = "%s domain=%s" % (append_line, domain)

            # A similar issue exists with suite name, as installer requires
            # the existence of "stable" in the dists directory
            append_line = "%s suite=%s" % (append_line, distro.os_version)

        # append necessary kernel args for arm architectures
        if arch is not None and arch.startswith("arm"):
            append_line = "%s fixrtc vram=48M omapfb.vram=0:24M" % append_line

        # do variable substitution on the append line
        # promote all of the autoinstall_meta variables
        if "autoinstall_meta" in blended:
            blended.update(blended["autoinstall_meta"])
        append_line = self.templar.render(append_line, utils.flatten(blended), None)

        # For now console=ttySx,BAUDRATE are only set for systems
        # This could get enhanced for profile/distro via utils.blender (inheritance)
        # This also is architecture specific. E.g: Some ARM consoles need: console=ttyAMAx,BAUDRATE
        # I guess we need a serial_kernel_dev = param, that can be set to "ttyAMA" if needed.
        if system:
            if (system.serial_device is not None) or (system.serial_baud_rate is not None):
                if system.serial_device:
                    serial_device = system.serial_device
                else:
                    serial_device = 0
                if system.serial_baud_rate:
                    serial_baud_rate = system.serial_baud_rate
                else:
                    serial_baud_rate = 115200

                append_line = "%s console=ttyS%s,%s" % (append_line, serial_device, serial_baud_rate)

        # FIXME - the append_line length limit is architecture specific
        if len(append_line) >= 1023:
            self.logger.warning("warning: kernel option length exceeds 1023")

        return append_line