summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cobbler/action_buildiso.py168
-rw-r--r--cobbler/api.py7
-rwxr-xr-xcobbler/cobbler.py19
-rw-r--r--cobbler/modules/cli_misc.py28
-rw-r--r--cobbler/remote.py4
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)