summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--AUTHORS1
-rw-r--r--CHANGELOG1
-rw-r--r--MANIFEST.in1
-rw-r--r--Makefile6
-rw-r--r--cobbler/action_import.py273
-rw-r--r--cobbler/api.py4
-rw-r--r--cobbler/codes.py3
-rw-r--r--cobbler/modules/cli_misc.py4
-rw-r--r--contrib/cloner/base.cfg1
-rw-r--r--docs/cobbler.pod2
-rw-r--r--kickstarts/sample.seed45
-rw-r--r--setup.py3
12 files changed, 234 insertions, 110 deletions
diff --git a/AUTHORS b/AUTHORS
index 3bf3698e..26737cba 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -35,6 +35,7 @@ Patches and other contributions from:
Jim Meyering <jim@meyering.net>
Perry Myers <pmyers@redhat.com>
Jack Neely <jjneely@ncsu.edu>
+ Javier Palacious <javiplx@gmail.com>
Lassi Pölönen <lassi.polonen@helsinki.fi>
Ben Riggs <rigg0022@umn.edu>
Jeremy Rosengren <jeremy@rosengren.org>
diff --git a/CHANGELOG b/CHANGELOG
index 8a6f0eaa..939bbe28 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -8,6 +8,7 @@ Cobbler CHANGELOG
see https://fedorahosted.org/cobbler/wiki/UsingCobblerWithConfigManagementSystem
- (FEAT) ability to use --enable-menu=0/1 to hide profiles from the PXE menu, and config setting to change default value for --enable-menu
- (FEAT) added livecd based physical machine cloner script to "contrib"
+- (FEAT) enable import for debian ISOs and mirrors (1 distro at a time for now)
- ??? - 1.2.5 (pending)
- (BUGF) expose --arch for "cobbler image add"
diff --git a/MANIFEST.in b/MANIFEST.in
index e7821624..ee1db3c9 100644
--- a/MANIFEST.in
+++ b/MANIFEST.in
@@ -18,6 +18,7 @@ include config/cobbler_bash
include config/cheetah_macros
recursive-include templates *.template
recursive-include kickstarts *.ks
+recursive-include kickstarts *.seed
include docs/cobbler.1.gz
include docs/cobbler.html
include docs/wui.html
diff --git a/Makefile b/Makefile
index c82097a3..85b6f8b7 100644
--- a/Makefile
+++ b/Makefile
@@ -104,6 +104,12 @@ eraseconfig:
-rm /var/lib/cobbler/profiles*
-rm /var/lib/cobbler/systems*
-rm /var/lib/cobbler/repos*
+ -rm /var/lib/cobbler/config/distros.d/*
+ -rm /var/lib/cobbler/config/images.d/*
+ -rm /var/lib/cobbler/config/profiles.d/*
+ -rm /var/lib/cobbler/config/systems.d/
+ -rm /var/lib/cobbler/config/repos.d/*
+
graphviz:
dot -Tpdf docs/cobbler.dot -o cobbler.pdf
diff --git a/cobbler/action_import.py b/cobbler/action_import.py
index babdafd3..e4c08368 100644
--- a/cobbler/action_import.py
+++ b/cobbler/action_import.py
@@ -37,6 +37,7 @@ WGET_CMD = "wget --mirror --no-parent --no-host-directories --directory-prefix %
RSYNC_CMD = "rsync -a %s '%s' %s/ks_mirror/%s --exclude-from=/etc/cobbler/rsync.exclude --progress"
TRY_LIST = [
+ "pool",
"Fedora", "Packages", "RedHat", "Client", "Server", "Centos", "CentOS",
"Fedora/RPMS", "RedHat/RPMS", "Client/RPMS", "Server/RPMS", "Centos/RPMS",
"CentOS/RPMS", "RPMS"
@@ -44,7 +45,7 @@ TRY_LIST = [
class Importer:
- def __init__(self,api,config,mirror,mirror_name,network_root=None,kickstart_file=None,rsync_flags=None,arch=None):
+ def __init__(self,api,config,mirror,mirror_name,network_root=None,kickstart_file=None,rsync_flags=None,arch=None,breed=None):
"""
Performs an import of a install tree (or trees) from the given
mirror address. The prefix of the distro is to be specified
@@ -68,6 +69,7 @@ class Importer:
self.kickstart_file = kickstart_file
self.rsync_flags = rsync_flags
self.arch = arch
+ self.breed = breed
# ----------------------------------------------------------------------
@@ -78,31 +80,30 @@ class Importer:
raise CX(_("import failed. no --name specified"))
if self.arch is not None:
self.arch = self.arch.lower()
- if self.arch not in [ "i386", "x86", "ia64", "x86_64", "s390x" ]:
- raise CX(_("arch must be x86, x86_64, s390x, or ia64"))
if self.arch == "x86":
# be consistent
self.arch = "i386"
+ if self.arch not in [ "i386", "ia64", "x86_64", "s390x" ]:
+ raise CX(_("arch must be i386, ia64, x86_64, or s390x"))
mpath = os.path.join(self.settings.webdir, "ks_mirror", self.mirror_name)
if os.path.exists(mpath) and self.arch is None:
+ # FIXME : Raise exception even when network_root is given ?
raise CX(_("Something already exists at this import location (%s). You must specify --arch to avoid potentially overwriting existing files.") % mpath)
if self.arch:
# append the arch path to the name if the arch is not already
# found in the name.
- found = False
for x in [ "ia64", "i386", "x86_64", "x86", "s390x" ]:
if self.mirror_name.lower().find(x) != -1:
- found = True
+ if self.arch != x :
+ raise CX(_("Architecture found on pathname (%s) does not fit the one given in command line (%s)")%(x,self.arch))
break
- if not found:
+ else:
+ # FIXME : This is very likely removed later at get_proposed_name, and the guessed arch appended again
self.mirror_name = self.mirror_name + "-" + self.arch
- if self.mirror_name is None:
- raise CX(_("import failed. no --name specified"))
-
# make the output path and mirror content but only if not specifying that a network
# accessible support location already exists
@@ -139,18 +140,17 @@ class Importer:
if not self.network_root.endswith("/"):
self.network_root = self.network_root + "/"
self.path = self.mirror
- found_root = False
valid_roots = [ "nfs://", "ftp://", "http://" ]
for valid_root in valid_roots:
if self.network_root.startswith(valid_root):
- found_root = True
+ break
+ else:
+ raise CX(_("Network root given to --available-as must be nfs://, ftp://, or http://"))
if self.network_root.startswith("nfs://"):
try:
(a,b,rest) = self.network_root.split(":",3)
except:
raise CX(_("Network root given to --available-as is missing a colon, please see the manpage example."))
- if not found_root:
- raise CX(_("Network root given to --available-as must be nfs://, ftp://, or http://"))
self.processed_repos = {}
@@ -175,6 +175,9 @@ class Importer:
def mkdir(self, dir):
try:
os.makedirs(dir)
+ except OSError , ex:
+ if ex.strerror == "Permission denied":
+ raise CX(_("Permission denied at %s")%dir)
except:
pass
@@ -203,9 +206,10 @@ class Importer:
# print _("- skipping distro %s since it wasn't imported this time") % profile.distro
continue
- if (self.kickstart_file == None):
+ if self.kickstart_file == None:
kdir = os.path.dirname(distro.kernel)
- base_dir = "/".join(kdir.split("/")[0:-2])
+ # FIXME : Some special handling for network_root might be required as in get_proposed_name,
+ base_dir = "/".join(kdir.split("/")[:6])
for try_entry in TRY_LIST:
try_dir = os.path.join(base_dir, try_entry)
@@ -220,7 +224,20 @@ class Importer:
(flavor, major, minor) = results
# print _("- finding default kickstart template for %(flavor)s %(major)s") % { "flavor" : flavor, "major" : major }
kickstart = self.set_variance(profile, flavor, major, minor, distro)
+ if not rpms:
+ # search for base-files or base-installer ?
+ rpms = glob.glob(os.path.join(try_dir, "main/b/base-files" , "base-files_*"))
+ for rpm in rpms:
+ results = self.scan_deb_filename(rpm)
+ if results is None:
+ continue
+ (flavor, major, minor) = results
+ if self.breed and self.breed != flavor:
+ raise CX(_("Error: given breed does not match imported tree"))
+ # print _("- finding default kickstart template for %(flavor)s %(major)s") % { "flavor" : flavor, "major" : major }
+ kickstart = self.set_variance(profile, flavor, major, minor, distro)
else:
+ # FIXME : Why not fix this while initially creating the profile ?
print _("- using kickstart file %s") % self.kickstart_file
profile.set_kickstart(self.kickstart_file)
@@ -329,6 +346,23 @@ class Importer:
if major >= 5:
return profile.set_kickstart("/etc/cobbler/sample.ks")
+ if flavor == "debian":
+
+ distro.set_breed("debian")
+ dist_names = { '4.0' : "Etch" , '5.0' : "Lenny" }
+ dist_vers = "%s.%s" % ( major , minor )
+ distro.set_os_version("debian%s" % dist_names[dist_vers])
+ return profile.set_kickstart("/etc/cobbler/sample.seed")
+
+ if flavor == "ubuntu":
+
+ distro.set_breed("ubuntu")
+ # Release names taken from wikipedia
+ dist_names = { '4.10':"WartyWarthog", '5.4':"HoaryHedgehog", '5.10':"BreezyBadger", '6.4':"DapperDrake", '6.10':"EdgyEft", '7.4':"FeistyFawn", '7.10':"GutsyGibbon", '8.4':"HardyHeron", '8.10':"IntrepidIbex", '9.4':"JauntyJackalope" }
+ dist_vers = "%s.%s" % ( major , minor )
+ distro.set_os_version("ubuntu%s" % dist_names[dist_vers])
+ return profile.set_kickstart("/etc/cobbler/sample.seed")
+
print _("- using default kickstart file choice")
return profile.set_kickstart("/etc/cobbler/legacy.ks")
@@ -378,6 +412,35 @@ class Importer:
minor = float(accum[1])
return (flavor, major, minor)
+ def scan_deb_filename(self, deb):
+ """
+ Determine what the distro is based on the base-files dpkg filename.
+ """
+
+ deb = os.path.basename(deb)
+
+ # now get the flavor:
+ flavor = "debian"
+ if deb.lower().find("ubuntu") != -1:
+ flavor = "ubuntu"
+
+ # get all the tokens and try to guess a version
+ accum = []
+ tokens = deb.split("_")
+ tokens2 = tokens[1].split(".")
+ for t2 in tokens2:
+ try:
+ val = int(t2)
+ accum.append(val)
+ except:
+ pass
+ if flavor == "ubuntu":
+ accum.pop(0)
+ accum.pop(0)
+ accum.append(0)
+
+ return (flavor, accum[0], accum[1])
+
# ----------------------------------------------------------------------
def distro_adder(self,foo,dirname,fnames):
@@ -389,17 +452,27 @@ class Importer:
fullname = os.path.join(dirname,x)
if os.path.islink(fullname) and os.path.isdir(fullname):
+ if os.path.realpath(fullname) == os.path.realpath(dirname):
+ if not self.breed:
+ self.breed = x
+ elif self.breed != x:
+ print "- WARNING - symlink name (%s) does not fit the breed (%s)" % ( x , self.breed )
+ continue
print "- following symlink: %s" % fullname
os.path.walk(fullname, self.distro_adder, {})
if x.startswith("initrd"):
initrd = os.path.join(dirname,x)
if x.startswith("vmlinuz") or x.startswith("kernel.img"):
+ # This ugly trick is to avoid inclusion of powerpc kernels from debian distros
+ if x.find("initrd") != -1:
+ continue
kernel = os.path.join(dirname,x)
if initrd is not None and kernel is not None and dirname.find("isolinux") == -1:
self.add_entry(dirname,kernel,initrd)
- path_parts = kernel.split("/")[:-2]
- comps_path = "/".join(path_parts)
+ # The values are reset because debian media has extra initrd images
+ initrd = None
+ kernel = None
@@ -411,7 +484,8 @@ class Importer:
print _("- traversing distro %s") % distro.name
if distro.kernel.find("ks_mirror") != -1:
basepath = os.path.dirname(distro.kernel)
- top = "/".join(basepath.split("/")[0:-2]) # up one level
+ # FIXME : Some special handling for network_root might be required as in get_proposed_name,
+ top = "/".join(basepath.split("/")[:6])
print _("- descent into %s") % top
os.path.walk(top, self.repo_scanner, distro)
else:
@@ -525,46 +599,50 @@ class Importer:
def add_entry(self,dirname,kernel,initrd):
- pxe_arch = self.get_pxe_arch(dirname)
- name = self.get_proposed_name(dirname, pxe_arch)
+ for pxe_arch in self.get_pxe_arch(dirname):
+ name = self.get_proposed_name(dirname, pxe_arch)
- existing_distro = self.distros.find(name=name)
+ existing_distro = self.distros.find(name=name)
- if existing_distro is not None:
- print _("- modifying existing distro: %s") % name
- distro = existing_distro
- else:
- print _("- creating new distro: %s") % name
- distro = self.config.new_distro()
+ if existing_distro is not None:
+ raise CX(_("Distro %s does already exists") % name)
+ print _("- modifying existing distro: %s") % name
+ distro = existing_distro
+ else:
+ print _("- creating new distro: %s") % name
+ distro = self.config.new_distro()
- distro.set_name(name)
- distro.set_kernel(kernel)
- distro.set_initrd(initrd)
- distro.set_arch(pxe_arch)
- distro.source_repos = []
- self.distros.add(distro,save=True)
- self.distros_added.append(distro)
-
- existing_profile = self.profiles.find(name=name)
-
- if existing_profile is None:
- print _("- creating new profile: %s") % name
- profile = self.config.new_profile()
- else:
- print _("- modifying existing profile: %s") % name
- profile = existing_profile
-
- profile.set_name(name)
- profile.set_distro(name)
- if name.find("-xen") != -1:
- profile.set_virt_type("xenpv")
- else:
- profile.set_virt_type("qemu")
-
- self.profiles.add(profile,save=True)
- self.api.serialize()
+ distro.set_name(name)
+ distro.set_kernel(kernel)
+ distro.set_initrd(initrd)
+ distro.set_arch(pxe_arch)
+ if self.breed:
+ distro.set_breed(self.breed)
+ distro.source_repos = []
+ self.distros.add(distro,save=True)
+ self.distros_added.append(distro)
+
+ existing_profile = self.profiles.find(name=name)
+
+ if existing_profile is None:
+ print _("- creating new profile: %s") % name
+ profile = self.config.new_profile()
+ else:
+ raise CX(_("Profile %s does already exists") % name)
+ print _("- modifying existing profile: %s") % name
+ profile = existing_profile
+
+ profile.set_name(name)
+ profile.set_distro(name)
+ #if self.kickstart_file:
+ # profile.set_kickstart(self.kickstart_file)
+ if name.find("-xen") != -1:
+ profile.set_virt_type("xenpv")
+ else:
+ profile.set_virt_type("qemu")
- return distro
+ self.profiles.add(profile,save=True)
+ self.api.serialize()
def get_proposed_name(self,dirname,pxe_arch):
archname = pxe_arch
@@ -580,23 +658,18 @@ class Importer:
if name.startswith("-"):
name = name[1:]
name = self.mirror_name + "-" + name
+ # FIXME : Why do we clean all these suffixes ?
name = name.replace("-os","")
name = name.replace("-images","")
name = name.replace("-tree","")
name = name.replace("var-www-cobbler-", "")
name = name.replace("ks_mirror-","")
name = name.replace("-pxeboot","")
+ name = name.replace("-install","")
name = name.replace("--","-")
- name = name.replace("-i386","")
- name = name.replace("_i386","")
- name = name.replace("-x86_64","")
- name = name.replace("_x86_64","")
- name = name.replace("-ia64","")
- name = name.replace("_ia64","")
- name = name.replace("-x86","")
- name = name.replace("_x86","")
- name = name.replace("-s390x","")
- name = name.replace("_s390x","")
+ for separator in [ '-' , '_' , '.' ] :
+ for arch in [ "i386" , "x86_64" , "ia64" , "x86" , "s390x" , "386" , "amd" ]:
+ name = name.replace("%s%s" % ( separator , arch ),"")
# ensure arch is on the end, regardless of path used.
name = name + "-" + archname
@@ -608,53 +681,44 @@ class Importer:
"""
# don't care about certain directories
- match = False
for x in TRY_LIST:
if dirname.find(x) != -1:
- match = True
- continue
- if not match:
+ break
+ else:
return
# try to find a kernel header RPM and then look at it's arch.
for x in fnames:
- if not x.endswith("rpm"):
+ if not x.endswith("rpm") and not x.endswith("deb"):
continue
- if x.find("kernel-header") != -1:
+ if x.find("kernel-header") != -1 or x.find("linux-headers-") != -1:
print _("- kernel header found: %s") % x
- if x.find("i386") != -1:
- foo["result"] = "i386"
- return
- elif x.find("x86_64") != -1:
- foo["result"] = "x86_64"
- return
- elif x.find("ia64") != -1:
- foo["result"] = "ia64"
- return
- elif x.find("s390") != -1:
- foo["result"] = "s390x"
- return
+ for arch in [ "i386" , "x86_64" , "ia64" , "s390x" ]:
+ if x.find(arch) != -1:
+ foo[arch] = 1
+ if x.find("amd64") != -1:
+ foo["x86_64"] = 1
+ if x.find("i686") != -1:
+ foo["i386"] = 1
+
+ if foo.keys():
+ return
# This extra code block is a temporary fix for rhel4.x 64bit [x86_64]
# distro ARCH identification-- L.M.
# NOTE: eventually refactor to merge in with the above block
for x in fnames:
- if not x.endswith("rpm"):
+ if not x.endswith("rpm") and not x.endswith("deb"):
continue
- if x.find("kernel-largesmp") != -1:
+ if x.find("kernel-largesmp") != -1 or x.find("kernel-hugemem") != -1 or x.find("linux-headers-") != -1:
print _("- kernel header found: %s") % x
- if x.find("i386") != -1:
- foo["result"] = "i386"
- return
- elif x.find("x86_64") != -1:
- foo["result"] = "x86_64"
- return
- elif x.find("ia64") != -1:
- foo["result"] = "ia64"
- return
- elif x.find("s390") != -1:
- foo["result"] = "s390x"
- return
+ for arch in [ "i386" , "x86_64" , "ia64" , "s390x" ]:
+ if x.find(arch) != -1:
+ foo[arch] = 1
+ if x.find("amd64") != -1:
+ foo["x86_64"] = 1
+ if x.find("i686") != -1:
+ foo["i386"] = 1
def learn_arch_from_tree(self,dirname):
"""
@@ -663,21 +727,22 @@ class Importer:
figure out the arch name. This is important for producing predictable distro names (and profile names)
from differing import sources
"""
- dirname2 = "/".join(dirname.split("/")[:-2]) # up two from images, then down as many as needed
+ # FIXME : Some special handling for network_root might be required as in get_proposed_name,
+ dirname2 = "/".join(dirname.split("/")[:6])
print _("- scanning %s for architecture info") % dirname2
- result = { "result" : "i386" } # default, but possibly not correct ...
+ result = {}
os.path.walk(dirname2, self.arch_walker, result)
- return result["result"]
+ return result.keys()
def get_pxe_arch(self,dirname):
t = dirname.lower()
- if t.find("x86_64") != -1:
- return "x86_64"
+ if t.find("x86_64") != -1 or t.find("amd") != -1:
+ return [ "x86_64" ]
if t.find("ia64") != -1:
- return "ia64"
+ return [ "ia64" ]
if t.find("i386") != -1 or t.find("386") != -1 or t.find("x86") != -1:
- return "i386"
+ return [ "i386" ]
if t.find("s390") != -1:
- return "s390x"
+ return [ "s390x" ]
return self.learn_arch_from_tree(dirname)
diff --git a/cobbler/api.py b/cobbler/api.py
index 817877ab..f0ade5d1 100644
--- a/cobbler/api.py
+++ b/cobbler/api.py
@@ -410,7 +410,7 @@ class BootAPI:
statusifier = action_status.BootStatusReport(self._config,mode)
return statusifier.run()
- def import_tree(self,mirror_url,mirror_name,network_root=None,kickstart_file=None,rsync_flags=None,arch=None):
+ def import_tree(self,mirror_url,mirror_name,network_root=None,kickstart_file=None,rsync_flags=None,arch=None,breed=None):
"""
Automatically import a directory tree full of distribution files.
mirror_url can be a string that represents a path, a user@host
@@ -420,7 +420,7 @@ class BootAPI:
"""
self.log("import_tree",[mirror_url, mirror_name, network_root, kickstart_file, rsync_flags])
importer = action_import.Importer(
- self, self._config, mirror_url, mirror_name, network_root, kickstart_file, rsync_flags, arch
+ self, self._config, mirror_url, mirror_name, network_root, kickstart_file, rsync_flags, arch, breed
)
return importer.run()
diff --git a/cobbler/codes.py b/cobbler/codes.py
index fc7529af..ff4e1d72 100644
--- a/cobbler/codes.py
+++ b/cobbler/codes.py
@@ -37,13 +37,14 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
# the rest are undefined (for now), this will evolve.
VALID_OS_BREEDS = [
- "redhat", "debian", "suse", "generic", "windows", "unix", "other"
+ "redhat", "debian", "ubuntu", "suse", "generic", "windows", "unix", "other"
]
VALID_OS_VERSIONS = {
"redhat" : [ "rhel2.1", "rhel3", "rhel4", "rhel5", "fedora5", "fedora6", "fedora7", "fedora8", "fedora9", "generic24", "generic26", "other" ],
"suse" : [ "sles10", "generic24", "generic26", "other" ],
"debian" : [ "debianEtch", "debianLenny", "generic24", "generic26", "other" ],
+ "ubuntu" : [ "ubuntuWartyWarthog", "ubuntuHoaryHedgehog", "ubuntuBreezyBadger", "ubuntuDapperDrake", "ubuntuEdgyEft", "ubuntuFeistyFawn", "ubuntuGutsyGibbon", "ubuntuHardyHeron", "ubuntuIntrepidIbex", "ubuntuJauntyJackalope" ],
"generic" : [ "generic24", "generic26", "other" ],
"windows" : [ "winxp", "win2k", "win2k3", "vista", "other" ],
"unix" : [ "solaris9", "solaris10", "freebsd6", "openbsd4", "other" ],
diff --git a/cobbler/modules/cli_misc.py b/cobbler/modules/cli_misc.py
index f92094a0..fdc8d69b 100644
--- a/cobbler/modules/cli_misc.py
+++ b/cobbler/modules/cli_misc.py
@@ -74,6 +74,7 @@ class ImportFunction(commands.CobblerFunction):
def add_options(self, p, args):
p.add_option("--arch", dest="arch", help="explicitly specify the architecture being imported (RECOMENDED)")
+ p.add_option("--breed", dest="breed", help="explicitly specify the breed being imported (RECOMENDED)")
p.add_option("--path", dest="mirror", help="local path or rsync location (REQUIRED)")
p.add_option("--mirror", dest="mirror_alt", help="alias for --path")
p.add_option("--name", dest="name", help="name, ex 'RHEL-5', (REQUIRED)")
@@ -94,7 +95,8 @@ class ImportFunction(commands.CobblerFunction):
network_root=self.options.available_as,
kickstart_file=self.options.kickstart_file,
rsync_flags=self.options.rsync_flags,
- arch=self.options.arch
+ arch=self.options.arch,
+ breed=self.options.breed
)
diff --git a/contrib/cloner/base.cfg b/contrib/cloner/base.cfg
index 6beada74..d4b1ee6b 100644
--- a/contrib/cloner/base.cfg
+++ b/contrib/cloner/base.cfg
@@ -19,7 +19,6 @@ services --disable sshd
repo --name=todos --baseurl=http://download.fedora.redhat.com/pub/fedora/linux/releases/9/Everything/i386/os/
repo --name=updatez --baseurl=http://download.fedora.redhat.com/pub/fedora/linux/updates/9/i386/
-repo --name=newkoan --baseurl=file:///tmp/newkoan/
text
bootloader --location=mbr
diff --git a/docs/cobbler.pod b/docs/cobbler.pod
index d48b85f3..7c2585ad 100644
--- a/docs/cobbler.pod
+++ b/docs/cobbler.pod
@@ -485,7 +485,7 @@ B<cobbler distro add --name=rhel4u3 --kernel=/dir1/vmlinuz --initrd=/dir1/initrd
B<cobbler distro add --name=fc5 --kernel=/dir2/vmlinuz --initrd=/dir2/initrd.img>
-B<cobbler profile add --name=fc5webservers --distro=fc5-i386 --kickstart=/dir4/kick.ks --kopts="something_to_make_my_gfx_card_work=42,some_other_parameter=foo">
+B<cobbler profile add --name=fc5webservers --distro=fc5-i386 --kickstart=/dir4/kick.ks --kopts="something_to_make_my_gfx_card_work=42 some_other_parameter=foo">
B<cobbler profile add --name=rhel4u3dbservers --distro=rhel4u3 --kickstart=/dir5/kick.ks>
diff --git a/kickstarts/sample.seed b/kickstarts/sample.seed
new file mode 100644
index 00000000..9335dc1a
--- /dev/null
+++ b/kickstarts/sample.seed
@@ -0,0 +1,45 @@
+#platform=x86, AMD64, or Intel EM64T
+# System authorization information
+
+# System bootloader configuration
+
+# Partition clearing information
+
+# Use text mode install
+
+# Firewall configuration
+
+# Run the Setup Agent on first boot
+
+# System keyboard
+d-i console-setup/dont_ask_layout note
+d-i console-setup/layoutcode string us
+d-i console-setup/layout select U.S. English
+# System language
+
+# Use network installation
+#d-i mirror/http/hostname string mirror.domain
+#d-i mirror/http/directory string /debian_directory
+# If any cobbler repo definitions were referenced in the kickstart profile, include them here.
+
+# Network information
+
+# Reboot after installation
+finish-install finish-install/reboot_in_progress note
+
+#Root password
+d-i passwd/root-password-crypted password \$1\$mF86/UHC\$WvcIcX2t6crBz2onWxyac.
+user-setup-udeb passwd/root-login boolean true
+user-setup-udeb passwd/make-user boolean false
+# SELinux configuration
+
+# Do not configure the X Window System
+
+# System timezone
+clock-setup clock-setup/utc boolean false
+tzsetup-udeb time/zone select America/New_York
+# Install OS instead of upgrade
+
+# Clear the Master Boot Record
+
+
diff --git a/setup.py b/setup.py
index a7ea8f20..67e540e1 100644
--- a/setup.py
+++ b/setup.py
@@ -102,6 +102,9 @@ if __name__ == "__main__":
(etcpath, ['kickstarts/sample.ks']),
(etcpath, ['kickstarts/sample_end.ks']),
(etcpath, ['kickstarts/default.ks']),
+
+ # seed files for debian
+ (etcpath, ['kickstarts/sample.seed']),
# templates for DHCP, DNS, and syslinux configs
(etcpath, ['templates/dhcp.template']),