diff options
-rw-r--r-- | AUTHORS | 1 | ||||
-rw-r--r-- | CHANGELOG | 1 | ||||
-rw-r--r-- | MANIFEST.in | 1 | ||||
-rw-r--r-- | Makefile | 6 | ||||
-rw-r--r-- | cobbler/action_import.py | 273 | ||||
-rw-r--r-- | cobbler/api.py | 4 | ||||
-rw-r--r-- | cobbler/codes.py | 3 | ||||
-rw-r--r-- | cobbler/modules/cli_misc.py | 4 | ||||
-rw-r--r-- | contrib/cloner/base.cfg | 1 | ||||
-rw-r--r-- | docs/cobbler.pod | 2 | ||||
-rw-r--r-- | kickstarts/sample.seed | 45 | ||||
-rw-r--r-- | setup.py | 3 |
12 files changed, 234 insertions, 110 deletions
@@ -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> @@ -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 @@ -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 + + @@ -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']), |