Example #1
0
    def generate_kickstart(self, profile=None, system=None):

        obj = system
        if system is None:
            obj = profile

        meta = utils.blender(self.api, False, obj)
        kickstart_path = utils.find_kickstart(meta["kickstart"])

        if not kickstart_path:
            return "# kickstart is missing or invalid: %s" % meta["kickstart"]

        ksmeta = meta["ks_meta"]
        del meta["ks_meta"]
        meta.update(ksmeta) # make available at top level
        meta["yum_repo_stanza"] = self.generate_repo_stanza(obj, (system is None))
        meta["yum_config_stanza"] = self.generate_config_stanza(obj, (system is None))
        meta["kernel_options"] = utils.hash_to_string(meta["kernel_options"])
        # meta["config_template_files"] = self.generate_template_files_stanza(g, False)

        try:
            raw_data = utils.read_file_contents(kickstart_path, self.api.logger,
                    self.settings.template_remote_kickstarts)
            if raw_data is None:
                return "# kickstart is sourced externally: %s" % meta["kickstart"]
            data = self.templar.render(raw_data, meta, None, obj)
            return data
        except FileNotFoundException:
            self.api.logger.warning("kickstart not found: %s" % meta["kickstart"])
            return "# kickstart not found: %s" % meta["kickstart"]
Example #2
0
    def generate_kickstart(self, profile=None, system=None):

        obj = system
        if system is None:
            obj = profile

        meta = utils.blender(self.api, False, obj)
        kickstart_path = utils.find_kickstart(meta["kickstart"])

        if not kickstart_path:
            return "# kickstart is missing or invalid: %s" % meta["kickstart"]

        ksmeta = meta["ks_meta"]
        del meta["ks_meta"]
        meta.update(ksmeta)  # make available at top level
        meta["yum_repo_stanza"] = self.generate_repo_stanza(
            obj, (system is None))
        meta["yum_config_stanza"] = self.generate_config_stanza(
            obj, (system is None))
        meta["kernel_options"] = utils.hash_to_string(meta["kernel_options"])
        # meta["config_template_files"] = self.generate_template_files_stanza(g, False)

        try:
            raw_data = utils.read_file_contents(
                kickstart_path, self.api.logger,
                self.settings.template_remote_kickstarts)
            if raw_data is None:
                return "# kickstart is sourced externally: %s" % meta[
                    "kickstart"]
            data = self.templar.render(raw_data, meta, None, obj)
            return data
        except FileNotFoundException:
            self.api.logger.warning("kickstart not found: %s" %
                                    meta["kickstart"])
            return "# kickstart not found: %s" % meta["kickstart"]
Example #3
0
    def generate_kickstart_for_profile(self,g):

        g = self.api.find_profile(name=g)
        if g is None:
           return "# profile not found"

        distro = g.get_conceptual_parent()
        meta = utils.blender(self.api, False, g)
        if distro is None:
           raise CX(_("profile %(profile)s references missing distro %(distro)s") % { "profile" : g.name, "distro" : g.distro })
        kickstart_path = utils.find_kickstart(meta["kickstart"])
        if kickstart_path is not None and os.path.exists(kickstart_path):
            # the input is an *actual* file, hence we have to copy it
            try:
                meta = utils.blender(self.api, False, g)
                ksmeta = meta["ks_meta"]
                del meta["ks_meta"]
                meta.update(ksmeta) # make available at top level
                meta["yum_repo_stanza"] = self.generate_repo_stanza(g,True)
                meta["yum_config_stanza"] = self.generate_config_stanza(g,True)
                meta["kickstart_done"]  = self.generate_kickstart_signal(0, g, None)
                meta["kickstart_start"] = self.generate_kickstart_signal(1, g, None)
                meta["kernel_options"] = utils.hash_to_string(meta["kernel_options"])
                kfile = open(kickstart_path)
                data = self.templar.render(kfile, meta, None, g)
                kfile.close()
                return data
            except:
                utils.log_exc(self.api.logger)
                raise

        elif kickstart_path is not None and not os.path.exists(kickstart_path):
            if kickstart_path.find("http://") == -1 and kickstart_path.find("ftp://") == -1 and kickstart_path.find("nfs:") == -1:
                return "# Error, cannot find %s" % kickstart_path
        return "# kickstart is sourced externally, or is missing, and cannot be displayed here: %s" % meta["kickstart"]
Example #4
0
    def generate_kickstart(self, profile=None, system=None):

        obj = system
        if system is None:
            obj = profile

        meta = utils.blender(self.api, False, obj)
        kickstart_path = utils.find_kickstart(meta["kickstart"])

        if not kickstart_path:
            return "# kickstart is missing or invalid: %s" % meta["kickstart"]

        ksmeta = meta["ks_meta"]
        del meta["ks_meta"]
        meta.update(ksmeta)  # make available at top level
        meta["yum_repo_stanza"] = self.generate_repo_stanza(
            obj, (system is None))
        meta["yum_config_stanza"] = self.generate_config_stanza(
            obj, (system is None))
        meta["kernel_options"] = utils.hash_to_string(meta["kernel_options"])
        # meta["config_template_files"] = self.generate_template_files_stanza(g, False)

        # add extra variables for other distro types
        if "tree" in meta:
            urlparts = urlparse.urlsplit(meta["tree"])
            meta["install_source_directory"] = urlparts[2]

        try:
            raw_data = utils.read_file_contents(
                kickstart_path, self.api.logger,
                self.settings.template_remote_kickstarts)
            if raw_data is None:
                return "# kickstart is sourced externally: %s" % meta[
                    "kickstart"]
            distro = profile.get_conceptual_parent()
            if system is not None:
                distro = system.get_conceptual_parent().get_conceptual_parent()

            data = self.templar.render(raw_data, meta, None, obj)

            if distro.breed == "suse":
                # AutoYaST profile
                data = self.generate_autoyast(profile, system, data)

            return data
        except FileNotFoundException:
            self.api.logger.warning("kickstart not found: %s" %
                                    meta["kickstart"])
            return "# kickstart not found: %s" % meta["kickstart"]
Example #5
0
    def start(self):

        self.create_backups()

        # fill up the knowledge piece array
        self.read_input()

        # iterate through all the knowledge pieces
        langs = []
        for lang, cat, subcat, desc, code in self.knowledge_piece_array:
            # handle cheatsheet retrieval (load or create)
            cht = self.handle_cheatsheet(lang)

            # handle the case if the category does not exist in the cheatsheet
            cat, exists = self.handle_category(cat, cht)

            if not exists:
                cht[cat] = []
            piece = self.create_current_knowledge_piece(
                cht, lang, cat, desc, code)

            # skip this knowledge piece if its already conteined in the cheatsheet
            if ''.join(cht[cat]).find(piece) != -1:
                self.add_msg(
                    "Knowledge piece already contained in cheatsheet!")
                continue

            # append the knowledge piece to the cheatsheet...
            cht[cat].append(piece)

            # ...and store it to disk!
            str_full = utils.hash_to_string(cht)
            a = open(self.wrapdir(lang), 'w')
            a.write(str_full)
            a.close()

            langs.append(lang)

        # compile the latex
        for lang in langs:
            self.compile_latex_docs(lang)

        self.add_msg(
            'All new knowledge has been intergrated. You may exit the program.'
        )
Example #6
0
    def make_s390_pseudo_pxe_menu(self):
        s390path = os.path.join(self.bootloc, "s390x")
        if not os.path.exists(s390path):
            utils.mkdir(s390path)
        profile_list = [profile for profile in self.profiles]
        image_list = [image for image in self.images]

        def sort_name(a, b):
            return cmp(a.name, b.name)

        profile_list.sort(sort_name)
        image_list.sort(sort_name)
        listfile = open(os.path.join(s390path, "profile_list"), "w+")
        for profile in profile_list:
            distro = profile.get_conceptual_parent()
            if distro is None:
                raise CX("profile is missing distribution: %s, %s" %
                         (profile.name, profile.distro))
            if distro.arch.startswith("s390"):
                listfile.write("%s\n" % profile.name)
                f2 = os.path.join(self.bootloc, "s390x", "p_%s" % profile.name)
                self.write_pxe_file(f2, None, profile, distro, distro.arch)
                cf = "%s_conf" % f2
                pf = "%s_parm" % f2
                template_cf = open("/etc/cobbler/pxe/s390x_conf.template")
                template_pf = open("/etc/cobbler/pxe/s390x_parm.template")
                blended = utils.blender(self.api, True, profile)
                self.templar.render(template_cf, blended, cf)
                # FIXME: profiles also need this data!
                # FIXME: the _conf and _parm files are limited to 80 characters in length
                try:
                    ipaddress = socket.gethostbyname_ex(
                        blended["http_server"])[2][0]
                except socket.gaierror:
                    ipaddress = blended["http_server"]
                kickstart_path = "http://%s/cblr/svc/op/ks/profile/%s" % (
                    ipaddress, profile.name)
                # gather default kernel_options and default kernel_options_s390x
                kopts = blended.get("kernel_options", "")
                hkopts = shlex.split(utils.hash_to_string(kopts))
                blended["kickstart_expanded"] = "ks=%s" % kickstart_path
                blended["kernel_options"] = hkopts
                self.templar.render(template_pf, blended, pf)

        listfile.close()
Example #7
0
    def generate_kickstart(self, profile=None, system=None):

        obj = system
        if system is None:
            obj = profile

        meta = utils.blender(self.api, False, obj)
        kickstart_path = utils.find_kickstart(meta["kickstart"])

        if not kickstart_path:
            return "# kickstart is missing or invalid: %s" % meta["kickstart"]

        ksmeta = meta["ks_meta"]
        del meta["ks_meta"]
        meta.update(ksmeta)     # make available at top level
        meta["yum_repo_stanza"] = self.generate_repo_stanza(obj, (system is None))
        meta["yum_config_stanza"] = self.generate_config_stanza(obj, (system is None))
        meta["kernel_options"] = utils.hash_to_string(meta["kernel_options"])

        # add extra variables for other distro types
        if "tree" in meta:
            urlparts = urlparse.urlsplit(meta["tree"])
            meta["install_source_directory"] = urlparts[2]

        try:
            raw_data = utils.read_file_contents(
                kickstart_path, self.api.logger,
                self.settings.template_remote_kickstarts)
            if raw_data is None:
                return "# kickstart is sourced externally: %s" % meta["kickstart"]
            distro = profile.get_conceptual_parent()
            if system is not None:
                distro = system.get_conceptual_parent().get_conceptual_parent()

            data = self.templar.render(raw_data, meta, None, obj)

            if distro.breed == "suse":
                # AutoYaST profile
                data = self.generate_autoyast(profile, system, data)

            return data
        except FileNotFoundException:
            self.api.logger.warning("kickstart not found: %s" % meta["kickstart"])
            return "# kickstart not found: %s" % meta["kickstart"]
Example #8
0
    def make_s390_pseudo_pxe_menu(self):
        s390path = os.path.join(self.bootloc, "s390x")
        if not os.path.exists(s390path):
            utils.mkdir(s390path)
        profile_list = [profile for profile in self.profiles]
        image_list = [image for image in self.images]

        def sort_name(a, b):
            return cmp(a.name, b.name)

        profile_list.sort(sort_name)
        image_list.sort(sort_name)
        listfile = open(os.path.join(s390path, "profile_list"), "w+")
        for profile in profile_list:
            distro = profile.get_conceptual_parent()
            if distro is None:
                raise CX("profile is missing distribution: %s, %s" % (profile.name, profile.distro))
            if distro.arch.startswith("s390"):
                listfile.write("%s\n" % profile.name)
                f2 = os.path.join(self.bootloc, "s390x", "p_%s" % profile.name)
                self.write_pxe_file(f2, None, profile, distro, distro.arch)
                cf = "%s_conf" % f2
                pf = "%s_parm" % f2
                template_cf = open("/etc/cobbler/pxe/s390x_conf.template")
                template_pf = open("/etc/cobbler/pxe/s390x_parm.template")
                blended = utils.blender(self.api, True, profile)
                self.templar.render(template_cf, blended, cf)
                # FIXME: profiles also need this data!
                # FIXME: the _conf and _parm files are limited to 80 characters in length
                try:
                    ipaddress = socket.gethostbyname_ex(blended["http_server"])[2][0]
                except socket.gaierror:
                    ipaddress = blended["http_server"]
                kickstart_path = "http://%s/cblr/svc/op/ks/profile/%s" % (ipaddress, profile.name)
                # gather default kernel_options and default kernel_options_s390x
                kopts = blended.get("kernel_options", "")
                hkopts = shlex.split(utils.hash_to_string(kopts))
                blended["kickstart_expanded"] = "ks=%s" % kickstart_path
                blended["kernel_options"] = hkopts
                self.templar.render(template_pf, blended, pf)

        listfile.close()
Example #9
0
    def generate_kickstart_for_system(self,s):


        s = self.api.find_system(name=s)
        if s is None:
            return "# system not found"

        profile = s.get_conceptual_parent()
        if profile is None:
            raise CX(_("system %(system)s references missing profile %(profile)s") % { "system" : s.name, "profile" : s.profile })
        distro = profile.get_conceptual_parent()
        if distro is None: 
            # this is an image parented system, no kickstart available
            return "# image based systems do not have kickstarts"
        meta = utils.blender(self.api, False, s)
        kickstart_path = utils.find_kickstart(meta["kickstart"])
        if kickstart_path and os.path.exists(kickstart_path):
            try:
                ksmeta = meta["ks_meta"]
                del meta["ks_meta"]
                meta.update(ksmeta) # make available at top level
                meta["yum_repo_stanza"] = self.generate_repo_stanza(s, False)
                meta["yum_config_stanza"] = self.generate_config_stanza(s, False)
                meta["kickstart_done"]  = self.generate_kickstart_signal(0, profile, s)
                meta["kickstart_start"] = self.generate_kickstart_signal(1, profile, s)
                meta["kernel_options"] = utils.hash_to_string(meta["kernel_options"])
                # meta["config_template_files"] = self.generate_template_files_stanza(g, False)
                kfile = open(kickstart_path)
                data = self.templar.render(kfile, meta, None, s)
                kfile.close()
                return data
            except:
                traceback.print_exc()
                raise CX(_("Error templating file"))
        elif kickstart_path is not None and not os.path.exists(kickstart_path):
            if kickstart_path.find("http://") == -1 and kickstart_path.find("ftp://") == -1 and kickstart_path.find("nfs:") == -1:
                return "# Error, cannot find %s" % kickstart_path
        return "# kickstart is sourced externally: %s" % meta["kickstart"]
Example #10
0
    def build_kernel_options(self, system, profile, distro, image, arch,
            kickstart_path):
        """
        Builds the full kernel options line.
        """

        if system is not None:
            blended = utils.blender(self.api, False, system)
        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())
        # support additional initrd= entries in kernel options.
        if "initrd" in kopts:
            append_line = ",%s" % kopts.pop("initrd")
        hkopts = utils.hash_to_string(kopts)
        append_line = "%s %s" % (append_line, hkopts)

        # kickstart path rewriting (get URLs for local files)
        if kickstart_path is not None and kickstart_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"]
            if system is not None and kickstart_path.startswith("/"):
                kickstart_path = "http://%s/cblr/svc/op/ks/system/%s" % (ipaddress, system.name)
            elif kickstart_path.startswith("/"):
                kickstart_path = "http://%s/cblr/svc/op/ks/profile/%s" % (ipaddress, profile.name)

            if distro.breed is None or distro.breed == "redhat":
                append_line = "%s ks=%s" % (append_line, kickstart_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, kickstart_path)
            elif distro.breed == "debian" or distro.breed == "ubuntu":
                append_line = "%s auto-install/enable=true priority=critical url=%s" % (append_line, kickstart_path)
            elif distro.breed == "freebsd":
                append_line = "%s ks=%s" % (append_line, kickstart_path)

                # rework kernel options for debian distros
                translations = { 'ksdevice':"interface" , 'lang':"locale" }
                for k,v in translations.iteritems():
                    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" % (kickstart_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, kickstart_path)
                # interface=bootif causes a failure
                append_line = append_line.replace("ksdevice=bootif","")

        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
        # FIXME: should we just promote all of the ksmeta 
        #        variables instead of just the tree?
        if blended.has_key("ks_meta") and blended["ks_meta"].has_key("tree"):
            blended["tree"] = blended["ks_meta"]["tree"]
        append_line = self.templar.render(append_line,utils.flatten(blended),None)

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

        return append_line
Example #11
0
    def write_all_system_files(self, system):

        profile = system.get_conceptual_parent()
        if profile is None:
            raise CX("system %(system)s references a missing profile %(profile)s" % { "system" : system.name, "profile" : system.profile})

        distro = profile.get_conceptual_parent()
        image_based = False
        image = None
        if distro is None:
            if profile.COLLECTION_TYPE == "profile":
               raise CX("profile %(profile)s references a missing distro %(distro)s" % { "profile" : system.profile, "distro" : profile.distro})
            else:
               image_based = True
               image = profile

        # hack: s390 generates files per system not per interface
        if not image_based and distro.arch.startswith("s390"):
            # Always write a system specific _conf and _parm file
            f2 = os.path.join(self.bootloc, "s390x", "s_%s" % system.name)
            cf = "%s_conf" % f2
            pf = "%s_parm" % f2
            template_cf = open("/etc/cobbler/pxe/s390x_conf.template")
            template_pf = open("/etc/cobbler/pxe/s390x_parm.template")
            blended = utils.blender(self.api, True, system)
            self.templar.render(template_cf, blended, cf)
            # FIXME: profiles also need this data!
            # FIXME: the _conf and _parm files are limited to 80 characters in length
            try: 
                ipaddress = socket.gethostbyname_ex(blended["http_server"])[2][0]
            except socket.gaierror:
                ipaddress = blended["http_server"]
            kickstart_path = "http://%s/cblr/svc/op/ks/system/%s" % (ipaddress, system.name)
            # gather default kernel_options and default kernel_options_s390x
            kopts = blended.get("kernel_options","")
            hkopts = shlex.split(utils.hash_to_string(kopts))
            blended["kickstart_expanded"] = "ks=%s" % kickstart_path
            blended["kernel_options"] = hkopts
            self.templar.render(template_pf, blended, pf)

            # Write system specific zPXE file
            if system.is_management_supported():
                self.write_pxe_file(f2, system, profile, distro, distro.arch)
            else:
                # ensure the file doesn't exist
                utils.rmfile(f2)
            return

        pxe_metadata = {'pxe_menu_items': self.get_menu_items()['pxe'] }
 
        # generate one record for each described NIC ..
 
        for (name,interface) in system.interfaces.iteritems():

            ip = interface["ip_address"]

            f1 = utils.get_config_filename(system, interface=name)
            if f1 is None:
                self.logger.warning("invalid interface recorded for system (%s,%s)" % (system.name,name))
                continue;

            if image_based:
                working_arch = image.arch
            else:
                working_arch = distro.arch

            if working_arch is None:
                raise "internal error, invalid arch supplied"

            # for tftp only ...
            grub_path = None
            if working_arch in [ "i386", "x86", "x86_64", "arm", "standard"]:
                # pxelinux wants a file named $name under pxelinux.cfg
                f2 = os.path.join(self.bootloc, "pxelinux.cfg", f1)

                # Only generating grub menus for these arch's:
                grub_path = os.path.join(self.bootloc, "grub", f1.upper())

            elif working_arch == "ia64":
                # elilo expects files to be named "$name.conf" in the root
                # and can not do files based on the MAC address
                if ip is not None and ip != "":
                    self.logger.warning("Warning: Itanium system object (%s) needs an IP address to PXE" % system.name)

                filename = "%s.conf" % utils.get_config_filename(system,interface=name)
                f2 = os.path.join(self.bootloc, filename)

            elif working_arch.startswith("ppc"):
                # Determine filename for system-specific yaboot.conf
                filename = "%s" % utils.get_config_filename(system, interface=name).lower()
                f2 = os.path.join(self.bootloc, "etc", filename)

                # Link to the yaboot binary
                f3 = os.path.join(self.bootloc, "ppc", filename)
                if os.path.lexists(f3):
                    utils.rmfile(f3)
                os.symlink("../yaboot", f3)
            else:
                continue 

            if system.is_management_supported():
                if not image_based:
                    self.write_pxe_file(f2, system, profile, distro, working_arch, metadata=pxe_metadata)
                    if grub_path:
                        self.write_pxe_file(grub_path, system, profile, distro, 
                                working_arch, format="grub")
                else:
                    self.write_pxe_file(f2, system, None, None, working_arch, image=profile, metadata=pxe_metadata)
            else:
                # ensure the file doesn't exist
                utils.rmfile(f2)
                if grub_path:
                    utils.rmfile(grub_path)
Example #12
0
    def write_pxe_file(self,filename,system,profile,distro,arch,image=None,include_header=True):
        """
        Write a configuration file for the boot loader(s).
        More system-specific configuration may come in later, if so
        that would appear inside the system object in api.py

        NOTE: relevant to tftp and pseudo-PXE (s390) only

        ia64 is mostly the same as syslinux stuff, s390 is a bit
        short-circuited and simpler.  All of it goes through the
        templating engine, see the templates in /etc/cobbler for
        more details
        """

        if arch is None:
            raise "missing arch"

        if image and not os.path.exists(image.file):
            return None  # nfs:// URLs or something, can't use for TFTP

        # ---
        # just some random variables
        template = None
        metadata = {}
        buffer = ""

        # ---
        kickstart_path = None
        kernel_path = None
        initrd_path = None

        if image is None: 
            # not image based, it's something normalish

            kernel_path = os.path.join("/images",distro.name,os.path.basename(distro.kernel))
            initrd_path = os.path.join("/images",distro.name,os.path.basename(distro.initrd))
        
            # Find the kickstart if we inherit from another profile
            if system:
	        blended = utils.blender(self.api, True, system)
            else:
                blended = utils.blender(self.api, True, profile)
            kickstart_path = blended.get("kickstart","")
            
        else:
            # this is an image we are making available, not kernel+initrd
            if image.image_type == "direct":
                kernel_path = os.path.join("/images2",image.name)
            elif image.image_type == "memdisk":
                kernel_path = "/memdisk"
                initrd_path = os.path.join("/images2",image.name)
            else:
                # CD-ROM ISO or virt-clone image? We can't PXE boot it.
                kernel_path = None
                initrd_path = None
        # ---
        # choose a template
        if system:
            if system.netboot_enabled:
                template = os.path.join(self.settings.pxe_template_dir,"pxesystem.template")
    
                if arch.startswith("s390"):
                    template = os.path.join(self.settings.pxe_template_dir,"pxesystem_s390x.template")
                elif arch == "ia64":
                    template = os.path.join(self.settings.pxe_template_dir,"pxesystem_ia64.template")
                elif arch.startswith("ppc"):
                    template = os.path.join(self.settings.pxe_template_dir,"pxesystem_ppc.template")
            else:
                # local booting on ppc requires removing the system-specific dhcpd.conf filename
                if arch is not None and arch.startswith("ppc"):
                    # Disable yaboot network booting for all interfaces on the system
                    for (name,interface) in system.interfaces.iteritems():

                        filename = "%s" % utils.get_config_filename(system, interface=name).lower()

                        # Remove symlink to the yaboot binary
                        f3 = os.path.join(self.bootloc, "ppc", filename)
                        if os.path.lexists(f3):
                            utils.rmfile(f3)

                        # Remove the interface-specific config file
                        f3 = os.path.join(self.bootloc, "etc", filename)
                        if os.path.lexists(f3):
                            utils.rmfile(f3)

                    # Yaboot/OF doesn't support booting locally once you've
                    # booted off the network, so nothing left to do
                    return None
                elif arch is not None and arch.startswith("s390"):
                    template = os.path.join(self.settings.pxe_template_dir,"pxelocal_s390x.template")
                elif arch is not None and arch.startswith("ia64"):
                    template = os.path.join(self.settings.pxe_template_dir,"pxelocal_ia64.template")
                else:
                    template = os.path.join(self.settings.pxe_template_dir,"pxelocal.template")
        else:
            # not a system record, so this is a profile record

            if arch.startswith("s390"):
                template = os.path.join(self.settings.pxe_template_dir,"pxeprofile_s390x.template")
            else:
                template = os.path.join(self.settings.pxe_template_dir,"pxeprofile.template")

        # now build the kernel command line
        if system is not None:
            blended = utils.blender(self.api, True, system)
        elif profile is not None:
            blended = utils.blender(self.api, True, profile)
        else:
            blended = utils.blender(self.api, True, image)
        kopts = blended.get("kernel_options","")

        # generate the append line
        hkopts = utils.hash_to_string(kopts)
        if initrd_path and (not arch or arch not in ["ia64", "ppc", "ppc64"]):
            append_line = "append initrd=%s %s" % (initrd_path, hkopts)
        else:
            append_line = "append %s" % hkopts

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

        # kickstart path rewriting (get URLs for local files)
        if kickstart_path is not None and kickstart_path != "":

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

            if system is not None and kickstart_path.startswith("/"):
                kickstart_path = "http://%s/cblr/svc/op/ks/system/%s" % (blended["http_server"], system.name)
            elif kickstart_path.startswith("/"):
                kickstart_path = "http://%s/cblr/svc/op/ks/profile/%s" % (blended["http_server"], profile.name)

            if distro.breed is None or distro.breed == "redhat":
                append_line = "%s ks=%s" % (append_line, kickstart_path)
            elif distro.breed == "suse":
                append_line = "%s autoyast=%s" % (append_line, kickstart_path)
            elif distro.breed == "debian" or distro.breed == "ubuntu":
                append_line = "%s auto url=%s" % (append_line, kickstart_path)

                # rework kernel options for debian distros
                translations = { 'ksdevice':"interface" , 'lang':"locale" }
                for k,v in translations.iteritems():
                    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":
                append_line = "%s vmkopts=debugLogToSerial:1 mem=512M ks=%s" % (append_line, kickstart_path)
                # interface=bootif causes a failure
                append_line = append_line.replace("ksdevice=bootif","")


        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:
                    # 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:
                hostname = profile.name

            # 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)

        if arch.startswith("ppc") or arch.startswith("s390"):
            # remove the prefix "append"
            append_line = append_line[7:]

        # store variables for templating
        metadata["menu_label"] = ""
        if profile:
            if not arch in [ "ia64", "ppc", "ppc64", "s390", "s390x" ]:
                metadata["menu_label"] = "MENU LABEL %s" % profile.name
                metadata["profile_name"] = profile.name
        elif image:
            metadata["menu_label"] = "MENU LABEL %s" % image.name
            metadata["profile_name"] = image.name

        if system:
            metadata["system_name"] = system.name

        if kernel_path is not None:
            metadata["kernel_path"] = kernel_path
        if initrd_path is not None:
            metadata["initrd_path"] = initrd_path

        metadata["append_line"] = append_line

        # get the template
        if kernel_path is not None:
            template_fh = open(template)
            template_data = template_fh.read()
            template_fh.close()
        else:
            # this is something we can't PXE boot
            template_data = "\n"        

        # save file and/or return results, depending on how called.
        buffer = self.templar.render(template_data, metadata, None)
        if filename is not None:
            self.logger.info("generating: %s" % filename)
            fd = open(filename, "w")
            fd.write(buffer)
            fd.close()
        return buffer
Example #13
0
    def build_kernel_options(self, system, profile, distro, image, arch,
                             kickstart_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 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())

        # 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 "ppc" in arch:
            for intf in 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['ksdevice'] = mac_address
                    break

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

        # kickstart path rewriting (get URLs for local files)
        if kickstart_path is not None and kickstart_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"]
            if system is not None and kickstart_path.startswith("/"):
                kickstart_path = "http://%s/cblr/svc/op/ks/system/%s" % (ipaddress, system.name)
            elif kickstart_path.startswith("/"):
                kickstart_path = "http://%s/cblr/svc/op/ks/profile/%s" % (ipaddress, profile.name)

            if distro.breed is None or distro.breed == "redhat":
                append_line = "%s ks=%s" % (append_line, kickstart_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, kickstart_path)
            elif distro.breed == "debian" or distro.breed == "ubuntu":
                append_line = "%s auto-install/enable=true priority=critical url=%s" % (append_line, kickstart_path)
                if management_interface:
                    append_line += " netcfg/choose_interface=%s" % management_interface
            elif distro.breed == "freebsd":
                append_line = "%s ks=%s" % (append_line, kickstart_path)

                # rework kernel options for debian distros
                translations = {'ksdevice': "interface", 'lang': "locale"}
                for k, v in translations.iteritems():
                    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" % (kickstart_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, kickstart_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, kickstart_path, img_path)
                    return append_line

        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)
        elif distro is not None and distro.breed == 'nexenta':
            append_line = "-B iso_nfs_path=%s:/var/www/cobbler/links/%s,auto_install=1" % (blended['next_server'], distro.name)

        # 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 ksmeta variables
        if "ks_meta" in blended:
            blended.update(blended["ks_meta"])
        append_line = self.templar.render(append_line, utils.flatten(blended), None)

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

        return append_line
Example #14
0
    def build_kernel_options(self, system, profile, distro, image, arch,
                             kickstart_path):
        """
        Builds the full kernel options line.
        """

        if system is not None:
            blended = utils.blender(self.api, False, system)
        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())
        # support additional initrd= entries in kernel options.
        if "initrd" in kopts:
            append_line = ",%s" % kopts.pop("initrd")
        hkopts = utils.hash_to_string(kopts)
        append_line = "%s %s" % (append_line, hkopts)
        # FIXME - the append_line length limit is architecture specific
        # TODO: why is this checked here, before we finish adding everything?
        if len(append_line) >= 255:
            self.logger.warning("warning: kernel option length exceeds 255")

        # kickstart path rewriting (get URLs for local files)
        if kickstart_path is not None and kickstart_path != "":

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

            ipaddress = socket.gethostbyname_ex(blended["http_server"])[2][0]
            if system is not None and kickstart_path.startswith("/"):
                kickstart_path = "http://%s/cblr/svc/op/ks/system/%s" % (
                    ipaddress, system.name)
            elif kickstart_path.startswith("/"):
                kickstart_path = "http://%s/cblr/svc/op/ks/profile/%s" % (
                    ipaddress, profile.name)

            if distro.breed is None or distro.breed == "redhat":
                append_line = "%s ks=%s" % (append_line, kickstart_path)
            elif distro.breed == "suse":
                append_line = "%s autoyast=%s" % (append_line, kickstart_path)
            elif distro.breed == "debian" or distro.breed == "ubuntu":
                append_line = "%s auto url=%s" % (append_line, kickstart_path)

                # rework kernel options for debian distros
                translations = {'ksdevice': "interface", 'lang': "locale"}
                for k, v in translations.iteritems():
                    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":
                append_line = "%s vmkopts=debugLogToSerial:1 mem=512M ks=%s" % \
                    (append_line, kickstart_path)
                # interface=bootif causes a failure
                append_line = append_line.replace("ksdevice=bootif", "")

        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:
                    # 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:
                hostname = profile.name

            # 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)

        return append_line
Example #15
0
    def build_kernel_options(self, system, profile, distro, image, arch,
                             kickstart_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 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())

        # 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 "ppc" in arch:
            for intf in 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['ksdevice'] = mac_address
                    break

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

        # kickstart path rewriting (get URLs for local files)
        if kickstart_path is not None and kickstart_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"]
            if system is not None and kickstart_path.startswith("/"):
                kickstart_path = "http://%s/cblr/svc/op/ks/system/%s" % (ipaddress, system.name)
            elif kickstart_path.startswith("/"):
                kickstart_path = "http://%s/cblr/svc/op/ks/profile/%s" % (ipaddress, profile.name)

            if distro.breed is None or distro.breed == "redhat":
                append_line = "%s ks=%s" % (append_line, kickstart_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, kickstart_path)
            elif distro.breed == "debian" or distro.breed == "ubuntu":
                append_line = "%s auto-install/enable=true priority=critical url=%s" % (append_line, kickstart_path)
                if management_interface:
                    append_line += " netcfg/choose_interface=%s" % management_interface
            elif distro.breed == "freebsd":
                append_line = "%s ks=%s" % (append_line, kickstart_path)

                # rework kernel options for debian distros
                translations = {'ksdevice': "interface", 'lang': "locale"}
                for k, v in translations.iteritems():
                    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" % (kickstart_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, kickstart_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, kickstart_path, img_path)
                    return append_line

        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)
        elif distro is not None and distro.breed == 'nexenta':
            append_line = "-B iso_nfs_path=%s:/var/www/cobbler/links/%s,auto_install=1" % (blended['next_server'], distro.name)

        # 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 ksmeta variables
        if "ks_meta" in blended:
            blended.update(blended["ks_meta"])
        append_line = self.templar.render(append_line, utils.flatten(blended), None)

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

        return append_line
Example #16
0
    def build_kernel_options(self, system, profile, distro, image, arch,
            kickstart_path):
        """
        Builds the full kernel options line.
        """

        if system is not None:
            blended = utils.blender(self.api, False, system)
        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())
        # support additional initrd= entries in kernel options.
        if "initrd" in kopts:
            append_line = ",%s" % kopts.pop("initrd")
        hkopts = utils.hash_to_string(kopts)
        append_line = "%s %s" % (append_line, hkopts)
        # FIXME - the append_line length limit is architecture specific
        # TODO: why is this checked here, before we finish adding everything?
        if len(append_line) >= 255:
            self.logger.warning("warning: kernel option length exceeds 255")

        # kickstart path rewriting (get URLs for local files)
        if kickstart_path is not None and kickstart_path != "":

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

            ipaddress = socket.gethostbyname_ex(blended["http_server"])[2][0]
            if system is not None and kickstart_path.startswith("/"):
                kickstart_path = "http://%s/cblr/svc/op/ks/system/%s" % (ipaddress, system.name)
            elif kickstart_path.startswith("/"):
                kickstart_path = "http://%s/cblr/svc/op/ks/profile/%s" % (ipaddress, profile.name)

            if distro.breed is None or distro.breed == "redhat":
                append_line = "%s ks=%s" % (append_line, kickstart_path)
            elif distro.breed == "suse":
                append_line = "%s autoyast=%s" % (append_line, kickstart_path)
            elif distro.breed == "debian" or distro.breed == "ubuntu":
                append_line = "%s auto url=%s" % (append_line, kickstart_path)

                # rework kernel options for debian distros
                translations = { 'ksdevice':"interface" , 'lang':"locale" }
                for k,v in translations.iteritems():
                    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" % (kickstart_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, kickstart_path)
                # interface=bootif causes a failure
                append_line = append_line.replace("ksdevice=bootif","")

        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:
                    # 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:
                hostname = profile.name

            # 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)

        return append_line
Example #17
0
    def write_pxe_file(self,
                       filename,
                       system,
                       profile,
                       distro,
                       arch,
                       image=None,
                       include_header=True):
        """
        Write a configuration file for the boot loader(s).
        More system-specific configuration may come in later, if so
        that would appear inside the system object in api.py

        NOTE: relevant to tftp and pseudo-PXE (s390) only

        ia64 is mostly the same as syslinux stuff, s390 is a bit
        short-circuited and simpler.  All of it goes through the
        templating engine, see the templates in /etc/cobbler for
        more details
        """

        if arch is None:
            raise "missing arch"

        if image and not os.path.exists(image.file):
            return None  # nfs:// URLs or something, can't use for TFTP

        # ---
        # just some random variables
        template = None
        metadata = {}
        buffer = ""

        # ---
        kickstart_path = None
        kernel_path = None
        initrd_path = None

        if image is None:
            # not image based, it's something normalish

            kernel_path = os.path.join("/images", distro.name,
                                       os.path.basename(distro.kernel))
            initrd_path = os.path.join("/images", distro.name,
                                       os.path.basename(distro.initrd))

            # Find the kickstart if we inherit from another profile
            if system:
                blended = utils.blender(self.api, True, system)
            else:
                blended = utils.blender(self.api, True, profile)
            kickstart_path = blended.get("kickstart", "")

        else:
            # this is an image we are making available, not kernel+initrd
            if image.image_type == "direct":
                kernel_path = os.path.join("/images2", image.name)
            elif image.image_type == "memdisk":
                kernel_path = "/memdisk"
                initrd_path = os.path.join("/images2", image.name)
            else:
                # CD-ROM ISO or virt-clone image? We can't PXE boot it.
                kernel_path = None
                initrd_path = None
        # ---
        # choose a template
        if system:
            if system.netboot_enabled:
                template = os.path.join(self.settings.pxe_template_dir,
                                        "pxesystem.template")

                if arch.startswith("s390"):
                    template = os.path.join(self.settings.pxe_template_dir,
                                            "pxesystem_s390x.template")
                elif arch == "ia64":
                    template = os.path.join(self.settings.pxe_template_dir,
                                            "pxesystem_ia64.template")
                elif arch.startswith("ppc"):
                    template = os.path.join(self.settings.pxe_template_dir,
                                            "pxesystem_ppc.template")
            else:
                # local booting on ppc requires removing the system-specific dhcpd.conf filename
                if arch is not None and arch.startswith("ppc"):
                    # Disable yaboot network booting for all interfaces on the system
                    for (name, interface) in system.interfaces.iteritems():

                        filename = "%s" % utils.get_config_filename(
                            system, interface=name).lower()

                        # Remove symlink to the yaboot binary
                        f3 = os.path.join(self.bootloc, "ppc", filename)
                        if os.path.lexists(f3):
                            utils.rmfile(f3)

                        # Remove the interface-specific config file
                        f3 = os.path.join(self.bootloc, "etc", filename)
                        if os.path.lexists(f3):
                            utils.rmfile(f3)

                    # Yaboot/OF doesn't support booting locally once you've
                    # booted off the network, so nothing left to do
                    return None
                elif arch is not None and arch.startswith("s390"):
                    template = os.path.join(self.settings.pxe_template_dir,
                                            "pxelocal_s390x.template")
                elif arch is not None and arch.startswith("ia64"):
                    template = os.path.join(self.settings.pxe_template_dir,
                                            "pxelocal_ia64.template")
                else:
                    template = os.path.join(self.settings.pxe_template_dir,
                                            "pxelocal.template")
        else:
            # not a system record, so this is a profile record

            if arch.startswith("s390"):
                template = os.path.join(self.settings.pxe_template_dir,
                                        "pxeprofile_s390x.template")
            else:
                template = os.path.join(self.settings.pxe_template_dir,
                                        "pxeprofile.template")

        # now build the kernel command line
        if system is not None:
            blended = utils.blender(self.api, True, system)
        elif profile is not None:
            blended = utils.blender(self.api, True, profile)
        else:
            blended = utils.blender(self.api, True, image)
        kopts = blended.get("kernel_options", "")

        # generate the append line
        hkopts = utils.hash_to_string(kopts)
        if initrd_path and (not arch or arch not in ["ia64", "ppc", "ppc64"]):
            append_line = "append initrd=%s %s" % (initrd_path, hkopts)
        else:
            append_line = "append %s" % hkopts

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

        # kickstart path rewriting (get URLs for local files)
        if kickstart_path is not None and kickstart_path != "":

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

            if system is not None and kickstart_path.startswith("/"):
                kickstart_path = "http://%s/cblr/svc/op/ks/system/%s" % (
                    blended["http_server"], system.name)
            elif kickstart_path.startswith("/"):
                kickstart_path = "http://%s/cblr/svc/op/ks/profile/%s" % (
                    blended["http_server"], profile.name)

            if distro.breed is None or distro.breed == "redhat":
                append_line = "%s ks=%s" % (append_line, kickstart_path)
            elif distro.breed == "suse":
                append_line = "%s autoyast=%s" % (append_line, kickstart_path)
            elif distro.breed == "debian" or distro.breed == "ubuntu":
                append_line = "%s auto url=%s" % (append_line, kickstart_path)

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

                # interface=bootif causes a failure
                append_line = append_line.replace("interface=bootif", "")

        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:
                    # 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:
                hostname = profile.name

            # 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)

        if arch.startswith("ppc") or arch.startswith("s390"):
            # remove the prefix "append"
            append_line = append_line[7:]

        # store variables for templating
        metadata["menu_label"] = ""
        if profile:
            if not arch in ["ia64", "ppc", "ppc64", "s390", "s390x"]:
                metadata["menu_label"] = "MENU LABEL %s" % profile.name
                metadata["profile_name"] = profile.name
        elif image:
            metadata["menu_label"] = "MENU LABEL %s" % image.name
            metadata["profile_name"] = image.name

        if system:
            metadata["system_name"] = system.name

        if kernel_path is not None:
            metadata["kernel_path"] = kernel_path
        if initrd_path is not None:
            metadata["initrd_path"] = initrd_path

        metadata["append_line"] = append_line

        # get the template
        if kernel_path is not None:
            template_fh = open(template)
            template_data = template_fh.read()
            template_fh.close()
        else:
            # this is something we can't PXE boot
            template_data = "\n"

        # save file and/or return results, depending on how called.
        buffer = self.templar.render(template_data, metadata, None)
        if filename is not None:
            self.logger.info("generating: %s" % filename)
            fd = open(filename, "w")
            fd.write(buffer)
            fd.close()
        return buffer