From b1bdd9f051d0d42e0fb1f69c7113786dfb7be3a5 Mon Sep 17 00:00:00 2001 From: Michael DeHaan Date: Wed, 14 Feb 2007 16:22:19 -0500 Subject: Working on adding pxemenu support. --- cobbler.spec | 1 - cobbler/action_sync.py | 147 ++++++++++++++++++++++++++++++++++++------------ cobbler/api.py | 3 + cobbler/config.py | 3 + cobbler/item_profile.py | 13 ++++- cobbler/utils.py | 1 + default.pxe | 10 ---- setup.py | 1 - 8 files changed, 130 insertions(+), 49 deletions(-) delete mode 100644 default.pxe diff --git a/cobbler.spec b/cobbler.spec index f2a98dc..977d668 100644 --- a/cobbler.spec +++ b/cobbler.spec @@ -88,7 +88,6 @@ test "x$RPM_BUILD_ROOT" != "x" && rm -rf $RPM_BUILD_ROOT %config(noreplace) /etc/cobbler/kickstart_fc6.ks %config(noreplace) /etc/cobbler/kickstart_fc6_domU.ks %config(noreplace) /etc/cobbler/dhcp.template -%config(noreplace) /etc/cobbler/default.pxe %config(noreplace) /etc/cobbler/rsync.exclude %dir %{python_sitelib}/cobbler %dir %{python_sitelib}/cobbler/yaml diff --git a/cobbler/action_sync.py b/cobbler/action_sync.py index 1ae9157..56d4538 100644 --- a/cobbler/action_sync.py +++ b/cobbler/action_sync.py @@ -70,6 +70,7 @@ class BootSync: if self.settings.manage_dhcp: self.write_dhcp_file() self.restart_dhcp() + self.make_tftp_menu() return True def restart_dhcp(self): @@ -494,16 +495,16 @@ class BootSync: # Copy default PXE file if it exists; if there's none, ignore # FIXME: Log something inobtrusive ifthe default file is missing - src = "/etc/cobbler/default.pxe" - if os.path.exists(src): - nocopy = False - for system in self.systems: - if system.name == "default": - nocopy = True - break - if not nocopy: - dst = os.path.join(self.settings.tftpboot, "pxelinux.cfg", "default") - self.copyfile(src, dst) + # src = "/etc/cobbler/default.pxe" + # if os.path.exists(src): + # nocopy = False + # for system in self.systems: + # if system.name == "default": + # nocopy = True + # break + # if not nocopy: + # dst = os.path.join(self.settings.tftpboot, "pxelinux.cfg", "default") + # self.copyfile(src, dst) for system in self.systems: self.write_all_system_files(system) @@ -560,9 +561,59 @@ class BootSync: return "01-" + "-".join(name.split(":")).lower() else: raise cexceptions.CobblerException("err_resolv", name) - - - def write_pxe_file(self,filename,system,profile,distro,is_ia64): + + def make_tftp_menu(self): + # only do this if there is NOT a system named default. + default = self.systems.find("default") + if default is not None: + return + # generate the defaults file: + fname = os.path.join(self.settings.tftpboot, "pxelinux.cfg", "default") + + # get menu categories + categories = {} + for profile in self.profiles: + categories[profile.pxe_category] = 1 + categories = categories.keys() + + defaults = open(fname, "w") + defaults.write("default local\n") + defaults.write("timeout 60\n") + defaults.write("prompt 1\n") + defaults.write("\n") + defaults.write("label local\n") + defaults.write("\tLOCALBOOT 0\n") + defaults.write("\n") + + categories.sort() + + for category in categories: + defaults.write("label %s\n" % category) + defaults.write("\tkernel menu.c32\n") + defaults.write("\tappend menu_%s\n" % category) + defaults.write("\n") + + catfile = open(os.path.join(self.settings.tftpboot, "pxelinux.cfg", "menu_%s" % category), "w") + profile_list = [profile for profile in self.profiles] + def sort_name(a,b): + return cmp(a.name,b.name) + profile_list.sort(sort_name) + for profile in profile_list: + + if profile.pxe_category == category: + catfile.write("label %s\n" % profile.name) + + # a evil invocation of the pxe file creation tool that only generates bits and pieces + # without a filename to write to, and without system interpolation, so it's basically just + # bits and pieces relevant to the profile. + distro = self.distros.find(profile.distro) + contents = self.write_pxe_file(None,None,profile,distro,False,include_header=False) + catfile.write(contents + "\n") + catfile.write("\n") + catfile.close() + defaults.close() + + def write_pxe_file(self,filename,system,profile,distro,is_ia64, include_header=True): """ Write a configuration file for the boot loader(s). More system-specific configuration may come in later, if so @@ -570,32 +621,45 @@ class BootSync: NOTE: relevant to tftp only """ + + buffer = "" + 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)) kickstart_path = profile.kickstart - fd = self.open_file(filename,"w+") + #fd = self.open_file(filename,"w+") + if not is_ia64: # pxelinux tree - self.tee(fd,"default linux\n") - self.tee(fd,"prompt 0\n") - self.tee(fd,"timeout 1\n") - self.tee(fd,"label linux\n") - self.tee(fd,"\tkernel %s\n" % kernel_path) + if include_header: + buffer = buffer + "default linux\n" + buffer = buffer + "prompt 0\n" + buffer = buffer + "timeout 1\n" + buffer = buffer + "label linux\n" + buffer = buffer + "\tkernel %s\n" % kernel_path else: # elilo thrown in root - self.tee(fd,"image=%s\n" % kernel_path) - self.tee(fd,"\tlabel=netinstall\n") - self.tee(fd,"\tinitrd=%s\n" % initrd_path) - self.tee(fd,"\tread-only\n") - self.tee(fd,"\troot=/dev/ram\n") + buffer = buffer + "image=%s\n" % kernel_path + buffer = buffer + "\tlabel=netinstall\n" + buffer = buffer + "\tinitrd=%s\n" % initrd_path + buffer = buffer + "\tread-only\n" + buffer = buffer + "\troot=/dev/ram\n" # now build the kernel command line - kopts = self.blend_options(True,( - self.settings.kernel_options, - profile.kernel_options, - distro.kernel_options, - system.kernel_options - )) + if system is not None: + kopts = self.blend_options(True,( + self.settings.kernel_options, + profile.kernel_options, + distro.kernel_options, + system.kernel_options + )) + else: + kopts = self.blend_options(True,( + self.settings.kernel_options, + profile.kernel_options, + distro.kernel_options + )) + # the kernel options line is common to elilo and pxelinux append_line = "%s" % self.hash_to_string(kopts) @@ -607,11 +671,15 @@ class BootSync: # kickstart path (if kickstart is used) if kickstart_path is not None and kickstart_path != "": + # if kickstart path is on disk, we've already copied it into # the HTTP mirror, so make it something anaconda can get at. - if kickstart_path.startswith("/") or kickstart_path.find("/cobbler/kickstarts/") != -1: + if system is not None and kickstart_path.startswith("/") or kickstart_path.find("/cobbler/kickstarts/") != -1: pxe_fn = self.get_pxe_filename(system.name) kickstart_path = "http://%s/cobbler_track/kickstarts_sys/%s/ks.cfg" % (self.settings.server, pxe_fn) + elif kickstart_path.startswith("/") or kickstart_path.find("/cobbler/kickstarts/") != -1: + kickstart_path = "http://%s/cobbler_track/kickstarts/%s/ks.cfg" % (self.settings.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": @@ -620,12 +688,18 @@ class BootSync: # now to add the append line to the file if not is_ia64: # pxelinux.cfg syntax - self.tee(fd, "\tappend %s" % append_line) + buffer = buffer + "\tappend %s" % append_line else: # elilo.conf syntax - self.tee(fd, "\tappend=\"%s\"" % append_line) + buffer = buffer + "\tappend=\"%s\"" % append_line + + if filename is not None: + fd = self.open_file(filename, "w") + self.tee(fd, buffer) + self.close_file(fd) + + return buffer - self.close_file(fd) def write_listings(self): """ @@ -762,7 +836,10 @@ class BootSync: return shutil.rmtree(path) except OSError, ioe: if not ioe.errno == errno.ENOENT: # doesn't exist - raise cexceptions.CobblerException("no_delete",path) + try: + self.rmfile(path) + except: + raise cexceptions.CobblerException("no_delete",path) return True def mkdir(self,path,mode=0777): diff --git a/cobbler/api.py b/cobbler/api.py index 2400b64..165c3f1 100644 --- a/cobbler/api.py +++ b/cobbler/api.py @@ -41,6 +41,9 @@ class BootAPI: """ return self._config.clear() + def __cmp(self,a,b): + return cmp(a.name,b.name) + def systems(self): """ Return the current list of systems diff --git a/cobbler/config.py b/cobbler/config.py index 44a7ab1..64d0287 100644 --- a/cobbler/config.py +++ b/cobbler/config.py @@ -49,6 +49,9 @@ class Config: ] self.file_check() + def __cmp(self,a,b): + return cmp(a.name,b.name) + def distros(self): """ Return the definitive copy of the Distros collection diff --git a/cobbler/item_profile.py b/cobbler/item_profile.py index a666bb4..badd5ff 100644 --- a/cobbler/item_profile.py +++ b/cobbler/item_profile.py @@ -40,17 +40,21 @@ class Profile(item.Item): self.virt_ram = 512 # MB. Install with 256 not likely to pass self.virt_paravirt = True # hvm support is *NOT* in Koan (now) self.repos = "" # names of cobbler repo definitions + self.pxe_category = "misc" def from_datastruct(self,seed_data): """ Load this object's properties based on seed_data """ + self.name = self.load_item(seed_data,'name') self.distro = self.load_item(seed_data,'distro') self.kickstart = self.load_item(seed_data,'kickstart') self.kernel_options = self.load_item(seed_data,'kernel_options') self.ks_meta = self.load_item(seed_data,'ks_meta') - self.repos = self.load_item(seed_data,'repos', "") + self.repos = self.load_item(seed_data,'repos', []) + self.pxe_category = self.load_item(seed_data,'pxe_category', 'misc') + # backwards compatibility if type(self.repos) != list: self.set_repos(self.repos) @@ -163,6 +167,10 @@ class Profile(item.Item): except: return cexceptions.CobblerException("exc_virt_ram") + def set_pxe_category(self, category): + self.pxe_category = category + return True + def set_virt_paravirt(self,truthiness): """ For Virt only. @@ -209,7 +217,8 @@ class Profile(item.Item): 'virt_ram' : self.virt_ram, 'virt_paravirt' : self.virt_paravirt, 'ks_meta' : self.ks_meta, - 'repos' : self.repos + 'repos' : self.repos, + 'pxe_category' : self.pxe_category } def printable(self): diff --git a/cobbler/utils.py b/cobbler/utils.py index add034f..8b678a5 100644 --- a/cobbler/utils.py +++ b/cobbler/utils.py @@ -192,6 +192,7 @@ def input_string_or_hash(options,delim=","): new_dict[tokens2[0]] = tokens2[1] else: return (False, {}) + new_dict.pop('', None) return (True, new_dict) else: options.pop('',None) diff --git a/default.pxe b/default.pxe deleted file mode 100644 index 76a172c..0000000 --- a/default.pxe +++ /dev/null @@ -1,10 +0,0 @@ -# This file is copied into /tftpboot/pxelinux.cfg/default -# and is the default boot file for systems that -# do not have a specific boot configuration. - -# Fall through to local boots -default local -timeout 1 -label local - localboot 0 - diff --git a/setup.py b/setup.py index 42888ed..6c98367 100644 --- a/setup.py +++ b/setup.py @@ -49,7 +49,6 @@ if __name__ == "__main__": (etcpath, ['kickstart_fc6_domU.ks']), (etcpath, ['default.ks']), (etcpath, ['dhcp.template']), - (etcpath, ['default.pxe']), (manpath, ['cobbler.1.gz']), (etcpath, ['rsync.exclude']), (initpath, ['cobblersyslogd']), -- cgit