From a389783b113ada0e3e33e8eb22e3b5a4b74db71e Mon Sep 17 00:00:00 2001 From: James Cammarata Date: Fri, 13 Feb 2009 00:46:28 -0600 Subject: buildiso --standalone 90% done still need to fix --tempdir deletion bug --- cobbler/action_buildiso.py | 199 ++++++++++++++++++++++++++++++++------------ cobbler/api.py | 4 +- cobbler/modules/cli_misc.py | 8 +- 3 files changed, 156 insertions(+), 55 deletions(-) diff --git a/cobbler/action_buildiso.py b/cobbler/action_buildiso.py index 7fa2c5aa..65dd4c35 100644 --- a/cobbler/action_buildiso.py +++ b/cobbler/action_buildiso.py @@ -29,6 +29,7 @@ import sys import traceback import shutil import sub_process +import re import utils from cexceptions import * @@ -68,8 +69,10 @@ class BuildIso: self.distros = config.distros() self.profiles = config.profiles() self.systems = config.systems() + self.distros = config.distros() self.distmap = {} self.distctr = 0 + self.source = "" def make_shorter(self,distname): if self.distmap.has_key(distname): @@ -79,44 +82,8 @@ class BuildIso: self.distmap[distname] = str(self.distctr) return str(self.distctr) - def run(self,iso=None,tempdir=None,profiles=None,systems=None): - - # if iso is none, create it in . as "kickstart.iso" - if iso is None: - iso = "kickstart.iso" - - if tempdir is None: - tempdir = os.path.join(os.getcwd(), "buildiso") - print _("- using/creating tempdir: %s") % tempdir - if not os.path.exists(tempdir): - os.makedirs(tempdir) - else: - shutil.rmtree(tempdir) - os.makedirs(tempdir) - - # if base of tempdir does not exist, fail - # create all profiles unless filtered by "profiles" - - imagesdir = os.path.join(tempdir, "images") - isolinuxdir = os.path.join(tempdir, "isolinux") - - print _("- building tree for isolinux") - if not os.path.exists(imagesdir): - os.makedirs(imagesdir) - if not os.path.exists(isolinuxdir): - os.makedirs(isolinuxdir) - - print _("- copying miscellaneous files") - isolinuxbin = "/usr/lib/syslinux/isolinux.bin" - menu = "/var/lib/cobbler/menu.c32" - chain = "/usr/lib/syslinux/chain.c32" - files = [ isolinuxbin, menu, chain ] - for f in files: - if not os.path.exists(f): - raise CX(_("Required file not found: %s") % f) - else: - utils.copyfile(f, os.path.join(isolinuxdir, os.path.basename(f)), self.api) - + + def generate_netboot_iso(self,imagesdir,isolinuxdir,profiles=None,systems=None): print _("- copying kernels and initrds - for profiles") # copy all images in included profiles to images dir for profile in self.api.profiles(): @@ -162,7 +129,7 @@ class BuildIso: isolinuxcfg = os.path.join(isolinuxdir, "isolinux.cfg") cfg = open(isolinuxcfg, "w+") cfg.write(HEADER) # fixme, use template - + print _("- generating profile list...") for profile in self.api.profiles(): use_this = True @@ -195,10 +162,10 @@ class BuildIso: length=len(append_line) if length>254: - print _("WARNING - append line length is greater than 254 chars: (%s chars)") % length - + print _("WARNING - append line length is greater than 254 chars: (%s chars)") % length + cfg.write(append_line) - + if systems is not None: print _("- generating system list...") @@ -252,26 +219,154 @@ class BuildIso: length=len(append_line) if length > 254: - print _("WARNING - append line length is greater than 254 chars: (%s chars)") % length - + print _("WARNING - append line length is greater than 254 chars: (%s chars)") % length + cfg.write(append_line) - print _("- done writing config") + print _("- done writing config") + cfg.write("\n") + cfg.write("MENU END\n") + cfg.close() + + + def generate_standalone_iso(self,imagesdir,isolinuxdir,distname,filesource): + + # Get the distro object for the requested distro + # and then get all of its descendants (profiles/sub-profiles/systems) + distro = self.api.find_distro(distname) + if distro is None: + raise CX("distro %s was not found, aborting" % distname) + descendants = distro.get_descendants() + + print _("- copying kernels and initrds - for standalone distro") + # tempdir/isolinux/$distro/vmlinuz, initrd.img + # FIXME: this will likely crash on non-Linux breeds + f1 = os.path.join(isolinuxdir, "%s.krn" % distname) + f2 = os.path.join(isolinuxdir, "%s.img" % distname) + if not os.path.exists(distro.kernel): + raise CX("path does not exist: %s" % distro.kernel) + if not os.path.exists(distro.initrd): + raise CX("path does not exist: %s" % distro.initrd) + shutil.copyfile(distro.kernel, f1) + shutil.copyfile(distro.initrd, f2) + + cmd = "rsync -rlptgu --exclude=boot.cat --exclude=TRANS.TBL %s/ %s/../" % (filesource, isolinuxdir) + print _("- copying distro %s files (%s)" % (distname,cmd)) + rc = sub_process.call(cmd, shell=True, close_fds=True) + if rc: + raise CX(_("rsync of files failed")) + + print _("- generating a isolinux.cfg") + isolinuxcfg = os.path.join(isolinuxdir, "isolinux.cfg") + cfg = open(isolinuxcfg, "w+") + cfg.write(HEADER) # fixme, use template + + for descendant in descendants: + data = utils.blender(self.api, True, descendant) + + cfg.write("\n") + cfg.write("LABEL %s\n" % descendant.name) + cfg.write(" MENU LABEL %s\n" % descendant.name) + cfg.write(" kernel %s.krn\n" % distname) + + data["kickstart"] = "cdrom:/isolinux/ks-%s.cfg" % descendant.name + + append_line = " append initrd=%s.img" % distname + append_line = append_line + " ks=%s " % data["kickstart"] + append_line = append_line + " %s\n" % data["kernel_options"] + + cfg.write(append_line) + + if descendant.COLLECTION_TYPE == 'profile': + kickstart_data = self.api.kickgen.generate_kickstart_for_profile(descendant.name) + elif descendant.COLLECTION_TYPE == 'system': + kickstart_data = self.api.kickgen.generate_kickstart_for_system(descendant.name) + + cdregex = re.compile("url .*\n", re.IGNORECASE) + kickstart_data = cdregex.sub("cdrom\n", kickstart_data) + + ks_name = os.path.join(isolinuxdir, "ks-%s.cfg" % descendant.name) + ks_file = open(ks_name, "w+") + ks_file.write(kickstart_data) + ks_file.close() + + print _("- done writing config") cfg.write("\n") cfg.write("MENU END\n") cfg.close() - + + return + + + def run(self,iso=None,tempdir=None,profiles=None,systems=None,distro=None,standalone=None,source=None): + + # the distro option is for stand-alone builds only + if not standalone and distro is not None: + raise CX(_("The --distro option should only be used when creating a standalone ISO")) + # if building standalone, we only want --distro, + # profiles/systems are disallowed + if standalone: + if profiles is not None or systems is not None: + raise CX(_("When building a standalone ISO, use --distro only instead of --profiles/--systems")) + elif distro is None: + raise CX(_("When building a standalone ISO, you must specify a --distro")) + elif source is None: + raise CX(_("When building a standalone ISO, you must specify a --source")) + elif not os.path.exists(source): + raise CX(_("The source specified (%s) does not exist" % source)) + + # if iso is none, create it in . as "kickstart.iso" + if iso is None: + iso = "kickstart.iso" + + if tempdir is None: + tempdir = os.path.join(os.getcwd(), "buildiso") + print _("- using/creating tempdir: %s") % tempdir + if not os.path.exists(tempdir): + os.makedirs(tempdir) + else: + shutil.rmtree(tempdir) + os.makedirs(tempdir) + + # if base of tempdir does not exist, fail + # create all profiles unless filtered by "profiles" + + imagesdir = os.path.join(tempdir, "images") + isolinuxdir = os.path.join(tempdir, "isolinux") + + print _("- building tree for isolinux") + if not os.path.exists(imagesdir): + os.makedirs(imagesdir) + if not os.path.exists(isolinuxdir): + os.makedirs(isolinuxdir) + + print _("- copying miscellaneous files") + isolinuxbin = "/usr/lib/syslinux/isolinux.bin" + menu = "/var/lib/cobbler/menu.c32" + chain = "/usr/lib/syslinux/chain.c32" + files = [ isolinuxbin, menu, chain ] + for f in files: + if not os.path.exists(f): + raise CX(_("Required file not found: %s") % f) + else: + utils.copyfile(f, os.path.join(isolinuxdir, os.path.basename(f)), self.api) + + if standalone: + self.generate_standalone_iso(imagesdir,isolinuxdir,distro,source) + else: + self.generate_netboot_iso(imagesdir,isolinuxdir,profiles,systems) + cmd = "mkisofs -o %s -r -b isolinux/isolinux.bin -c isolinux/boot.cat" % iso - cmd = cmd + " -no-emul-boot -boot-load-size 4 " - cmd = cmd + " -boot-info-table -V Cobbler\ Install -R -J -T %s" % tempdir + cmd = cmd + " -no-emul-boot -boot-load-size 4" + cmd = cmd + " -boot-info-table -V Cobbler\ Install -R -J -T %s" % tempdir print _("- running: %s") % cmd rc = sub_process.call(cmd, shell=True, close_fds=True) if rc: raise CX(_("mkisofs failed")) - + print _("ISO build complete") print _("You may wish to delete: %s") % tempdir - print _("The output file is: %s") % iso - - + print _("The output file is: %s") % iso + + diff --git a/cobbler/api.py b/cobbler/api.py index 0e563306..bbaca45a 100644 --- a/cobbler/api.py +++ b/cobbler/api.py @@ -677,10 +677,10 @@ class BootAPI: self.log("authorize",[user,resource,arg1,arg2,rc],debug=True) return rc - def build_iso(self,iso=None,profiles=None,systems=None,tempdir=None): + def build_iso(self,iso=None,profiles=None,systems=None,tempdir=None,distro=None,standalone=None,source=None): builder = action_buildiso.BuildIso(self._config) return builder.run( - iso=iso, profiles=profiles, systems=systems, tempdir=tempdir + iso=iso, profiles=profiles, systems=systems, tempdir=tempdir, distro=distro, standalone=standalone, source=source ) def replicate(self, cobbler_master = None, sync_all=False, sync_kickstarts=False, sync_trees=False, sync_repos=False, sync_triggers=False, systems=False): diff --git a/cobbler/modules/cli_misc.py b/cobbler/modules/cli_misc.py index 14e61ff5..5855a0a1 100644 --- a/cobbler/modules/cli_misc.py +++ b/cobbler/modules/cli_misc.py @@ -225,6 +225,9 @@ class BuildIsoFunction(commands.CobblerFunction): p.add_option("--profiles", dest="profiles", help="(OPTIONAL) use these profiles only") p.add_option("--systems", dest="systems", help="(OPTIONAL) use these systems only") p.add_option("--tempdir", dest="tempdir", help="(OPTIONAL) working directory") + p.add_option("--distro", dest="distro", help="(OPTIONAL) used with --standalone to create a distro-based ISO including all associated profiles/systems") + p.add_option("--standalone", dest="standalone", action="store_true", help="(OPTIONAL) creates a standalone ISO with all required distro files on it") + p.add_option("--source", dest="source", help="(OPTIONAL) used with --standalone to specify a source for the distribution files") def help_me(self): return HELP_FORMAT % ("cobbler buildiso","[ARGS]") @@ -237,7 +240,10 @@ class BuildIsoFunction(commands.CobblerFunction): iso=self.options.isoname, profiles=self.options.profiles, systems=self.options.systems, - tempdir=self.options.tempdir + tempdir=self.options.tempdir, + distro=self.options.distro, + standalone=self.options.standalone, + source=self.options.source ) ######################################################## -- cgit From f3af45e6db61b8af7c9dfcb3417ea7a1207c4bb6 Mon Sep 17 00:00:00 2001 From: James Cammarata Date: Fri, 13 Feb 2009 07:53:17 -0600 Subject: [CRIT] Fix for --tempdir deletion bug --- cobbler/action_buildiso.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/cobbler/action_buildiso.py b/cobbler/action_buildiso.py index 9a72fb23..a21a86bb 100644 --- a/cobbler/action_buildiso.py +++ b/cobbler/action_buildiso.py @@ -336,6 +336,14 @@ class BuildIso: if tempdir is None: tempdir = os.path.join(os.getcwd(), "buildiso") + else: + if not os.path.isdir(tempdir): + raise CX(_("The --tempdir specified is not a directory")) + + (tempdir_head,tempdir_tail) = os.path.split(os.path.normpath(tempdir)) + if tempdir_tail != "buildiso": + tempdir = os.path.join(tempdir, "buildiso") + print _("- using/creating tempdir: %s") % tempdir if not os.path.exists(tempdir): os.makedirs(tempdir) -- cgit From 83e78b67973be5f3c5d1d175e4884537dd783f87 Mon Sep 17 00:00:00 2001 From: James Cammarata Date: Mon, 23 Feb 2009 17:12:11 -0600 Subject: Troubleshooting, booting from iso did not like having the files named after the distro. Reverted names to vmlinuz and initrd.img and everything seems to work fine --- cobbler/action_buildiso.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/cobbler/action_buildiso.py b/cobbler/action_buildiso.py index a21a86bb..67546d5f 100644 --- a/cobbler/action_buildiso.py +++ b/cobbler/action_buildiso.py @@ -256,8 +256,8 @@ class BuildIso: print _("- copying kernels and initrds - for standalone distro") # tempdir/isolinux/$distro/vmlinuz, initrd.img # FIXME: this will likely crash on non-Linux breeds - f1 = os.path.join(isolinuxdir, "%s.krn" % distname) - f2 = os.path.join(isolinuxdir, "%s.img" % distname) + f1 = os.path.join(isolinuxdir, "vmlinuz") + f2 = os.path.join(isolinuxdir, "initrd.img") if not os.path.exists(distro.kernel): raise CX("path does not exist: %s" % distro.kernel) if not os.path.exists(distro.initrd): @@ -265,7 +265,7 @@ class BuildIso: shutil.copyfile(distro.kernel, f1) shutil.copyfile(distro.initrd, f2) - cmd = "rsync -rlptgu --exclude=boot.cat --exclude=TRANS.TBL %s/ %s/../" % (filesource, isolinuxdir) + cmd = "rsync -rlptgu --exclude=boot.cat --exclude=TRANS.TBL --exclude=isolinux/ %s/ %s/../" % (filesource, isolinuxdir) print _("- copying distro %s files (%s)" % (distname,cmd)) rc = sub_process.call(cmd, shell=True, close_fds=True) if rc: @@ -282,11 +282,11 @@ class BuildIso: cfg.write("\n") cfg.write("LABEL %s\n" % descendant.name) cfg.write(" MENU LABEL %s\n" % descendant.name) - cfg.write(" kernel %s.krn\n" % distname) + cfg.write(" kernel vmlinuz\n") data["kickstart"] = "cdrom:/isolinux/ks-%s.cfg" % descendant.name - append_line = " append initrd=%s.img" % distname + append_line = " append initrd=initrd.img" append_line = append_line + " ks=%s " % data["kickstart"] append_line = append_line + " %s\n" % data["kernel_options"] @@ -379,7 +379,7 @@ class BuildIso: else: self.generate_netboot_iso(imagesdir,isolinuxdir,profiles,systems) - cmd = "mkisofs -o %s -r -b isolinux/isolinux.bin -c isolinux/boot.cat" % iso + cmd = "mkisofs -quiet -o %s -r -b isolinux/isolinux.bin -c isolinux/boot.cat" % iso cmd = cmd + " -no-emul-boot -boot-load-size 4" cmd = cmd + " -boot-info-table -V Cobbler\ Install -R -J -T %s" % tempdir -- cgit