diff options
Diffstat (limited to 'cobbler')
-rw-r--r-- | cobbler/action_buildiso.py | 168 | ||||
-rw-r--r-- | cobbler/api.py | 7 | ||||
-rwxr-xr-x | cobbler/cobbler.py | 19 | ||||
-rw-r--r-- | cobbler/modules/cli_misc.py | 28 | ||||
-rw-r--r-- | cobbler/remote.py | 4 |
5 files changed, 210 insertions, 16 deletions
diff --git a/cobbler/action_buildiso.py b/cobbler/action_buildiso.py new file mode 100644 index 0000000..0a2edac --- /dev/null +++ b/cobbler/action_buildiso.py @@ -0,0 +1,168 @@ +""" +Builds non-live bootable CD's that have PXE-equivalent behavior +for all cobbler profiles currently in memory. + +Copyright 2006-2008, Red Hat, Inc +Michael DeHaan <mdehaan@redhat.com> + +This software may be freely redistributed under the terms of the GNU +general public license. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +""" + +import os +import os.path +import shutil +import sub_process +import sys +import traceback +import shutil +import sub_process + +import utils +from cexceptions import * +from utils import _ + +# FIXME: lots of overlap with pxegen.py, should consolidate +# FIXME: disable timeouts and remove local boot for this? +HEADER = """ + +DEFAULT menu +PROMPT 0 +MENU TITLE Cobbler | http://cobbler.et.redhat.com +TIMEOUT 200 +TOTALTIMEOUT 6000 +ONTIMEOUT local + +LABEL local + MENU LABEL (local) + MENU DEFAULT + LOCALBOOT 0 + +""" + +class BuildIso: + """ + Handles conversion of internal state to the tftpboot tree layout + """ + + def __init__(self,config,verbose=False): + """ + Constructor + """ + self.verbose = verbose + self.config = config + self.api = config.api + self.distros = config.distros() + self.profiles = config.profiles() + + def run(self,iso=None,tempdir=None,profiles=None): + + # verify we can find isolinux.bin + + if iso is None: + iso = "kickstart.iso" + + isolinuxbin = "/usr/lib/syslinux/isolinux.bin" + if not os.path.exists(isolinuxbin): + raise CX(_("Required file not found: %s") % isolinuxbin) + + # if iso is none, create it in . as "cobbler.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) + + # 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") + utils.copyfile(isolinuxbin, os.path.join(isolinuxdir, "isolinux.bin")) + menu = "/var/lib/cobbler/menu.c32" + files = [ isolinuxbin, menu ] + for f in files: + if not os.path.exists(f): + raise CX(_("Required file not found: %s") % f) + utils.copyfile(f, os.path.join(isolinuxdir, os.path.basename(f))) + + print _("- copying kernels and initrds") + # copy all images in included profiles to images dir + for x in self.api.profiles(): + use_this = True + if profiles is not None: + which_profiles = profiles.split(",") + if not use_this in which_profiles: + use_this = False + dist = x.get_conceptual_parent() + distdir = os.path.join(isolinuxdir, x.name) + if not os.path.exists(distdir): + os.makedirs(distdir) + # tempdir/isolinux/$distro/vmlinuz, initrd.img + # FIXME: this will likely crash on non-Linux breeds + shutil.copyfile(dist.kernel, os.path.join(distdir, "vmlinuz")) + shutil.copyfile(dist.initrd, os.path.join(distdir, "initrd.img")) + + # generate isolinux.cfg + print _("- generating a isolinux.cfg") + isolinuxcfg = os.path.join(isolinuxdir, "isolinux.cfg") + cfg = open(isolinuxcfg, "w+") + cfg.write(HEADER) # fixme, use template + + for x in self.api.profiles(): + # FIXME + use_this = True + if profiles is not None: + which_profiles = profiles.split(",") + if not use_this in which_profiles: + use_this = False + if use_this: + dist = x.get_conceptual_parent() + data = utils.blender(self.api, True, x) + + cfg.write("\n") + cfg.write("LABEL %s\n" % x.name) + cfg.write(" MENU LABEL %s\n" % x.name) + cfg.write(" kernel /%s/vmlinuz\n" % dist.name) + + if data["kickstart"].startswith("/"): + data["kickstart"] = "http://%s/cblr/svc/op/ks/profile/%s" % ( + data["server"], + x.name + ) + + append_line = " append %s/initrd.img" % dist.name + append_line = append_line + " ks=%s " % data["kickstart"] + append_line = append_line + " %s\n" % data["kernel_options"] + cfg.write(append_line) + + print _("- done writing config") + cfg.write("\n") + cfg.write("MENU END\n") + cfg.close() + + cmd = "mkisofs -o %s -r -b isolinux/isolinux.bin" % iso + 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) + 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 + + diff --git a/cobbler/api.py b/cobbler/api.py index 1814c41..7bcd4fa 100644 --- a/cobbler/api.py +++ b/cobbler/api.py @@ -22,6 +22,7 @@ import action_import import action_reposync import action_status import action_validate +import action_buildiso from cexceptions import * import sub_process import module_loader @@ -417,3 +418,9 @@ class BootAPI: self.log("authorize",[user,resource,arg1,arg2,rc],debug=True) return rc + def build_iso(self,iso=None,profiles=None,tempdir=None): + builder = action_buildiso.BuildIso(self._config) + return builder.run( + iso=iso, profiles=profiles, tempdir=tempdir + ) + diff --git a/cobbler/cobbler.py b/cobbler/cobbler.py index e8a2ef5..627e398 100755 --- a/cobbler/cobbler.py +++ b/cobbler/cobbler.py @@ -21,6 +21,7 @@ import os.path import traceback import optparse import commands +import cexceptions from cexceptions import * from utils import _ @@ -49,20 +50,16 @@ def main(): """ exitcode = 0 try: - # FIXME: redo locking code? return BootCLI().run(sys.argv) - except CX, exc: - print str(exc)[1:-1] # remove framing air quotes - except SystemExit: - pass # probably exited from optparse, nothing extra to print - except Exception, exc2: - if isinstance(exc2, CX) or isinstance(exc2, CobblerException): - traceback.print_exc() + except Exception, exc: + if isinstance(exc, cexceptions.CobblerException) or \ + isinstance(exc, cexceptions.CX) or \ + str(type(exc)).find("CX") != -1 or \ + str(type(exc)).find("CobblerException") != -1: + print str(exc)[1:-1] # remove framing air quotes else: - print str(exc2)[1:-1] # remove framing air quotes + traceback.print_exc() return 1 - return 1 - if __name__ == "__main__": sys.exit(main()) diff --git a/cobbler/modules/cli_misc.py b/cobbler/modules/cli_misc.py index af2f6b2..6ca14a2 100644 --- a/cobbler/modules/cli_misc.py +++ b/cobbler/modules/cli_misc.py @@ -184,11 +184,6 @@ class ReportFunction(commands.CobblerFunction): self.reporting_print_sorted(self.api.repos()) return True -## FIXME: add legacy command translator to keep things simple -## cobbler system report foo --> cobbler report --what=systems --name=foo -## cobbler system report --> cobbler report --what=systems -## ditto for "cobbler list" - ######################################################## class StatusFunction(commands.CobblerFunction): @@ -245,6 +240,28 @@ class ValidateKsFunction(commands.CobblerFunction): return self.api.validateks() ######################################################## + +class BuildIsoFunction(commands.CobblerFunction): + + def add_options(self,p,args): + p.add_option("--iso", dest="isoname", help="(OPTIONAL) output ISO to this path") + p.add_option("--profiles", dest="profiles", help="(OPTIONAL) use these profiles only") + p.add_option("--tempdir", dest="tempdir", help="(OPTIONAL) working directory") + + def help_me(self): + return HELP_FORMAT % ("cobbler buildiso","") + + def command_name(self): + return "buildiso" + + def run(self): + return self.api.build_iso( + iso=self.options.isoname, + profiles=self.options.profiles, + tempdir=self.options.tempdir + ) + +######################################################## # MODULE HOOKS def register(): @@ -255,6 +272,7 @@ def register(): def cli_functions(api): return [ + BuildIsoFunction(api), CheckFunction(api), ImportFunction(api), ReserializeFunction(api), ListFunction(api), ReportFunction(api), StatusFunction(api), SyncFunction(api), RepoSyncFunction(api), ValidateKsFunction(api) diff --git a/cobbler/remote.py b/cobbler/remote.py index a7e056b..18c3947 100644 --- a/cobbler/remote.py +++ b/cobbler/remote.py @@ -248,6 +248,10 @@ class CobblerXMLRPCInterface: if mac.find(" ") != -1: mac = mac.split()[-1] + dup = self.api.find_system(mac_address=mac) + if dup is not None: + return 4 + self.log("register mac for profile %s" % profile,token=token,name=mac) obj = self.api.new_system() obj.set_profile(profile) |