summaryrefslogtreecommitdiffstats
path: root/scripts/lib/wic/3rdparty/pykickstart
diff options
context:
space:
mode:
Diffstat (limited to 'scripts/lib/wic/3rdparty/pykickstart')
-rw-r--r--scripts/lib/wic/3rdparty/pykickstart/__init__.py0
-rw-r--r--scripts/lib/wic/3rdparty/pykickstart/base.py466
-rw-r--r--scripts/lib/wic/3rdparty/pykickstart/commands/__init__.py20
-rw-r--r--scripts/lib/wic/3rdparty/pykickstart/commands/bootloader.py216
-rw-r--r--scripts/lib/wic/3rdparty/pykickstart/commands/partition.py314
-rw-r--r--scripts/lib/wic/3rdparty/pykickstart/constants.py57
-rw-r--r--scripts/lib/wic/3rdparty/pykickstart/errors.py103
-rw-r--r--scripts/lib/wic/3rdparty/pykickstart/handlers/__init__.py0
-rw-r--r--scripts/lib/wic/3rdparty/pykickstart/handlers/control.py46
-rw-r--r--scripts/lib/wic/3rdparty/pykickstart/handlers/f16.py24
-rw-r--r--scripts/lib/wic/3rdparty/pykickstart/ko.py37
-rw-r--r--scripts/lib/wic/3rdparty/pykickstart/options.py204
-rw-r--r--scripts/lib/wic/3rdparty/pykickstart/parser.py702
-rw-r--r--scripts/lib/wic/3rdparty/pykickstart/sections.py244
-rw-r--r--scripts/lib/wic/3rdparty/pykickstart/version.py197
15 files changed, 2630 insertions, 0 deletions
diff --git a/scripts/lib/wic/3rdparty/pykickstart/__init__.py b/scripts/lib/wic/3rdparty/pykickstart/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/scripts/lib/wic/3rdparty/pykickstart/__init__.py
diff --git a/scripts/lib/wic/3rdparty/pykickstart/base.py b/scripts/lib/wic/3rdparty/pykickstart/base.py
new file mode 100644
index 0000000000..e6c8f56f9d
--- /dev/null
+++ b/scripts/lib/wic/3rdparty/pykickstart/base.py
@@ -0,0 +1,466 @@
+#
+# Chris Lumens <clumens@redhat.com>
+#
+# Copyright 2006, 2007, 2008 Red Hat, Inc.
+#
+# This copyrighted material is made available to anyone wishing to use, modify,
+# copy, or redistribute it subject to the terms and conditions of the GNU
+# General Public License v.2. This program is distributed in the hope that it
+# will be useful, but WITHOUT ANY WARRANTY expressed or implied, including the
+# implied warranties of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# See the GNU General Public License for more details.
+#
+# 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., 51
+# Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. Any Red Hat
+# trademarks that are incorporated in the source code or documentation are not
+# subject to the GNU General Public License and may only be used or replicated
+# with the express permission of Red Hat, Inc.
+#
+"""
+Base classes for creating commands and syntax version object.
+
+This module exports several important base classes:
+
+ BaseData - The base abstract class for all data objects. Data objects
+ are contained within a BaseHandler object.
+
+ BaseHandler - The base abstract class from which versioned kickstart
+ handler are derived. Subclasses of BaseHandler hold
+ BaseData and KickstartCommand objects.
+
+ DeprecatedCommand - An abstract subclass of KickstartCommand that should
+ be further subclassed by users of this module. When
+ a subclass is used, a warning message will be
+ printed.
+
+ KickstartCommand - The base abstract class for all kickstart commands.
+ Command objects are contained within a BaseHandler
+ object.
+"""
+import gettext
+gettext.textdomain("pykickstart")
+_ = lambda x: gettext.ldgettext("pykickstart", x)
+
+import types
+import warnings
+from pykickstart.errors import *
+from pykickstart.ko import *
+from pykickstart.parser import Packages
+from pykickstart.version import versionToString
+
+###
+### COMMANDS
+###
+class KickstartCommand(KickstartObject):
+ """The base class for all kickstart commands. This is an abstract class."""
+ removedKeywords = []
+ removedAttrs = []
+
+ def __init__(self, writePriority=0, *args, **kwargs):
+ """Create a new KickstartCommand instance. This method must be
+ provided by all subclasses, but subclasses must call
+ KickstartCommand.__init__ first. Instance attributes:
+
+ currentCmd -- The name of the command in the input file that
+ caused this handler to be run.
+ currentLine -- The current unprocessed line from the input file
+ that caused this handler to be run.
+ handler -- A reference to the BaseHandler subclass this
+ command is contained withing. This is needed to
+ allow referencing of Data objects.
+ lineno -- The current line number in the input file.
+ writePriority -- An integer specifying when this command should be
+ printed when iterating over all commands' __str__
+ methods. The higher the number, the later this
+ command will be written. All commands with the
+ same priority will be written alphabetically.
+ """
+
+ # We don't want people using this class by itself.
+ if self.__class__ is KickstartCommand:
+ raise TypeError, "KickstartCommand is an abstract class."
+
+ KickstartObject.__init__(self, *args, **kwargs)
+
+ self.writePriority = writePriority
+
+ # These will be set by the dispatcher.
+ self.currentCmd = ""
+ self.currentLine = ""
+ self.handler = None
+ self.lineno = 0
+
+ # If a subclass provides a removedKeywords list, remove all the
+ # members from the kwargs list before we start processing it. This
+ # ensures that subclasses don't continue to recognize arguments that
+ # were removed.
+ for arg in filter(kwargs.has_key, self.removedKeywords):
+ kwargs.pop(arg)
+
+ def __call__(self, *args, **kwargs):
+ """Set multiple attributes on a subclass of KickstartCommand at once
+ via keyword arguments. Valid attributes are anything specified in
+ a subclass, but unknown attributes will be ignored.
+ """
+ for (key, val) in kwargs.items():
+ # Ignore setting attributes that were removed in a subclass, as
+ # if they were unknown attributes.
+ if key in self.removedAttrs:
+ continue
+
+ if hasattr(self, key):
+ setattr(self, key, val)
+
+ def __str__(self):
+ """Return a string formatted for output to a kickstart file. This
+ method must be provided by all subclasses.
+ """
+ return KickstartObject.__str__(self)
+
+ def parse(self, args):
+ """Parse the list of args and set data on the KickstartCommand object.
+ This method must be provided by all subclasses.
+ """
+ raise TypeError, "parse() not implemented for KickstartCommand"
+
+ def apply(self, instroot="/"):
+ """Write out the configuration related to the KickstartCommand object.
+ Subclasses which do not provide this method will not have their
+ configuration written out.
+ """
+ return
+
+ def dataList(self):
+ """For commands that can occur multiple times in a single kickstart
+ file (like network, part, etc.), return the list that we should
+ append more data objects to.
+ """
+ return None
+
+ def deleteRemovedAttrs(self):
+ """Remove all attributes from self that are given in the removedAttrs
+ list. This method should be called from __init__ in a subclass,
+ but only after the superclass's __init__ method has been called.
+ """
+ for attr in filter(lambda k: hasattr(self, k), self.removedAttrs):
+ delattr(self, attr)
+
+ # Set the contents of the opts object (an instance of optparse.Values
+ # returned by parse_args) as attributes on the KickstartCommand object.
+ # It's useful to call this from KickstartCommand subclasses after parsing
+ # the arguments.
+ def _setToSelf(self, optParser, opts):
+ self._setToObj(optParser, opts, self)
+
+ # Sets the contents of the opts object (an instance of optparse.Values
+ # returned by parse_args) as attributes on the provided object obj. It's
+ # useful to call this from KickstartCommand subclasses that handle lists
+ # of objects (like partitions, network devices, etc.) and need to populate
+ # a Data object.
+ def _setToObj(self, optParser, opts, obj):
+ for key in filter (lambda k: getattr(opts, k) != None, optParser.keys()):
+ setattr(obj, key, getattr(opts, key))
+
+class DeprecatedCommand(KickstartCommand):
+ """Specify that a command is deprecated and no longer has any function.
+ Any command that is deprecated should be subclassed from this class,
+ only specifying an __init__ method that calls the superclass's __init__.
+ This is an abstract class.
+ """
+ def __init__(self, writePriority=None, *args, **kwargs):
+ # We don't want people using this class by itself.
+ if self.__class__ is KickstartCommand:
+ raise TypeError, "DeprecatedCommand is an abstract class."
+
+ # Create a new DeprecatedCommand instance.
+ KickstartCommand.__init__(self, writePriority, *args, **kwargs)
+
+ def __str__(self):
+ """Placeholder since DeprecatedCommands don't work anymore."""
+ return ""
+
+ def parse(self, args):
+ """Print a warning message if the command is seen in the input file."""
+ mapping = {"lineno": self.lineno, "cmd": self.currentCmd}
+ warnings.warn(_("Ignoring deprecated command on line %(lineno)s: The %(cmd)s command has been deprecated and no longer has any effect. It may be removed from future releases, which will result in a fatal error from kickstart. Please modify your kickstart file to remove this command.") % mapping, DeprecationWarning)
+
+
+###
+### HANDLERS
+###
+class BaseHandler(KickstartObject):
+ """Each version of kickstart syntax is provided by a subclass of this
+ class. These subclasses are what users will interact with for parsing,
+ extracting data, and writing out kickstart files. This is an abstract
+ class.
+
+ version -- The version this syntax handler supports. This is set by
+ a class attribute of a BaseHandler subclass and is used to
+ set up the command dict. It is for read-only use.
+ """
+ version = None
+
+ def __init__(self, mapping=None, dataMapping=None, commandUpdates=None,
+ dataUpdates=None, *args, **kwargs):
+ """Create a new BaseHandler instance. This method must be provided by
+ all subclasses, but subclasses must call BaseHandler.__init__ first.
+
+ mapping -- A custom map from command strings to classes,
+ useful when creating your own handler with
+ special command objects. It is otherwise unused
+ and rarely needed. If you give this argument,
+ the mapping takes the place of the default one
+ and so must include all commands you want
+ recognized.
+ dataMapping -- This is the same as mapping, but for data
+ objects. All the same comments apply.
+ commandUpdates -- This is similar to mapping, but does not take
+ the place of the defaults entirely. Instead,
+ this mapping is applied after the defaults and
+ updates it with just the commands you want to
+ modify.
+ dataUpdates -- This is the same as commandUpdates, but for
+ data objects.
+
+
+ Instance attributes:
+
+ commands -- A mapping from a string command to a KickstartCommand
+ subclass object that handles it. Multiple strings can
+ map to the same object, but only one instance of the
+ command object should ever exist. Most users should
+ never have to deal with this directly, as it is
+ manipulated internally and called through dispatcher.
+ currentLine -- The current unprocessed line from the input file
+ that caused this handler to be run.
+ packages -- An instance of pykickstart.parser.Packages which
+ describes the packages section of the input file.
+ platform -- A string describing the hardware platform, which is
+ needed only by system-config-kickstart.
+ scripts -- A list of pykickstart.parser.Script instances, which is
+ populated by KickstartParser.addScript and describes the
+ %pre/%post/%traceback script section of the input file.
+ """
+
+ # We don't want people using this class by itself.
+ if self.__class__ is BaseHandler:
+ raise TypeError, "BaseHandler is an abstract class."
+
+ KickstartObject.__init__(self, *args, **kwargs)
+
+ # This isn't really a good place for these, but it's better than
+ # everything else I can think of.
+ self.scripts = []
+ self.packages = Packages()
+ self.platform = ""
+
+ # These will be set by the dispatcher.
+ self.commands = {}
+ self.currentLine = 0
+
+ # A dict keyed by an integer priority number, with each value being a
+ # list of KickstartCommand subclasses. This dict is maintained by
+ # registerCommand and used in __str__. No one else should be touching
+ # it.
+ self._writeOrder = {}
+
+ self._registerCommands(mapping, dataMapping, commandUpdates, dataUpdates)
+
+ def __str__(self):
+ """Return a string formatted for output to a kickstart file."""
+ retval = ""
+
+ if self.platform != "":
+ retval += "#platform=%s\n" % self.platform
+
+ retval += "#version=%s\n" % versionToString(self.version)
+
+ lst = self._writeOrder.keys()
+ lst.sort()
+
+ for prio in lst:
+ for obj in self._writeOrder[prio]:
+ retval += obj.__str__()
+
+ for script in self.scripts:
+ retval += script.__str__()
+
+ retval += self.packages.__str__()
+
+ return retval
+
+ def _insertSorted(self, lst, obj):
+ length = len(lst)
+ i = 0
+
+ while i < length:
+ # If the two classes have the same name, it's because we are
+ # overriding an existing class with one from a later kickstart
+ # version, so remove the old one in favor of the new one.
+ if obj.__class__.__name__ > lst[i].__class__.__name__:
+ i += 1
+ elif obj.__class__.__name__ == lst[i].__class__.__name__:
+ lst[i] = obj
+ return
+ elif obj.__class__.__name__ < lst[i].__class__.__name__:
+ break
+
+ if i >= length:
+ lst.append(obj)
+ else:
+ lst.insert(i, obj)
+
+ def _setCommand(self, cmdObj):
+ # Add an attribute on this version object. We need this to provide a
+ # way for clients to access the command objects. We also need to strip
+ # off the version part from the front of the name.
+ if cmdObj.__class__.__name__.find("_") != -1:
+ name = unicode(cmdObj.__class__.__name__.split("_", 1)[1])
+ else:
+ name = unicode(cmdObj.__class__.__name__).lower()
+
+ setattr(self, name.lower(), cmdObj)
+
+ # Also, add the object into the _writeOrder dict in the right place.
+ if cmdObj.writePriority is not None:
+ if self._writeOrder.has_key(cmdObj.writePriority):
+ self._insertSorted(self._writeOrder[cmdObj.writePriority], cmdObj)
+ else:
+ self._writeOrder[cmdObj.writePriority] = [cmdObj]
+
+ def _registerCommands(self, mapping=None, dataMapping=None, commandUpdates=None,
+ dataUpdates=None):
+ if mapping == {} or mapping == None:
+ from pykickstart.handlers.control import commandMap
+ cMap = commandMap[self.version]
+ else:
+ cMap = mapping
+
+ if dataMapping == {} or dataMapping == None:
+ from pykickstart.handlers.control import dataMap
+ dMap = dataMap[self.version]
+ else:
+ dMap = dataMapping
+
+ if type(commandUpdates) == types.DictType:
+ cMap.update(commandUpdates)
+
+ if type(dataUpdates) == types.DictType:
+ dMap.update(dataUpdates)
+
+ for (cmdName, cmdClass) in cMap.iteritems():
+ # First make sure we haven't instantiated this command handler
+ # already. If we have, we just need to make another mapping to
+ # it in self.commands.
+ cmdObj = None
+
+ for (key, val) in self.commands.iteritems():
+ if val.__class__.__name__ == cmdClass.__name__:
+ cmdObj = val
+ break
+
+ # If we didn't find an instance in self.commands, create one now.
+ if cmdObj == None:
+ cmdObj = cmdClass()
+ self._setCommand(cmdObj)
+
+ # Finally, add the mapping to the commands dict.
+ self.commands[cmdName] = cmdObj
+ self.commands[cmdName].handler = self
+
+ # We also need to create attributes for the various data objects.
+ # No checks here because dMap is a bijection. At least, that's what
+ # the comment says. Hope no one screws that up.
+ for (dataName, dataClass) in dMap.iteritems():
+ setattr(self, dataName, dataClass)
+
+ def dispatcher(self, args, lineno):
+ """Call the appropriate KickstartCommand handler for the current line
+ in the kickstart file. A handler for the current command should
+ be registered, though a handler of None is not an error. Returns
+ the data object returned by KickstartCommand.parse.
+
+ args -- A list of arguments to the current command
+ lineno -- The line number in the file, for error reporting
+ """
+ cmd = args[0]
+
+ if not self.commands.has_key(cmd):
+ raise KickstartParseError, formatErrorMsg(lineno, msg=_("Unknown command: %s" % cmd))
+ elif self.commands[cmd] != None:
+ self.commands[cmd].currentCmd = cmd
+ self.commands[cmd].currentLine = self.currentLine
+ self.commands[cmd].lineno = lineno
+
+ # The parser returns the data object that was modified. This could
+ # be a BaseData subclass that should be put into a list, or it
+ # could be the command handler object itself.
+ obj = self.commands[cmd].parse(args[1:])
+ lst = self.commands[cmd].dataList()
+ if lst is not None:
+ lst.append(obj)
+
+ return obj
+
+ def maskAllExcept(self, lst):
+ """Set all entries in the commands dict to None, except the ones in
+ the lst. All other commands will not be processed.
+ """
+ self._writeOrder = {}
+
+ for (key, val) in self.commands.iteritems():
+ if not key in lst:
+ self.commands[key] = None
+
+ def hasCommand(self, cmd):
+ """Return true if there is a handler for the string cmd."""
+ return hasattr(self, cmd)
+
+
+###
+### DATA
+###
+class BaseData(KickstartObject):
+ """The base class for all data objects. This is an abstract class."""
+ removedKeywords = []
+ removedAttrs = []
+
+ def __init__(self, *args, **kwargs):
+ """Create a new BaseData instance.
+
+ lineno -- Line number in the ks-file where this object was defined
+ """
+
+ # We don't want people using this class by itself.
+ if self.__class__ is BaseData:
+ raise TypeError, "BaseData is an abstract class."
+
+ KickstartObject.__init__(self, *args, **kwargs)
+ self.lineno = 0
+
+ def __str__(self):
+ """Return a string formatted for output to a kickstart file."""
+ return ""
+
+ def __call__(self, *args, **kwargs):
+ """Set multiple attributes on a subclass of BaseData at once via
+ keyword arguments. Valid attributes are anything specified in a
+ subclass, but unknown attributes will be ignored.
+ """
+ for (key, val) in kwargs.items():
+ # Ignore setting attributes that were removed in a subclass, as
+ # if they were unknown attributes.
+ if key in self.removedAttrs:
+ continue
+
+ if hasattr(self, key):
+ setattr(self, key, val)
+
+ def deleteRemovedAttrs(self):
+ """Remove all attributes from self that are given in the removedAttrs
+ list. This method should be called from __init__ in a subclass,
+ but only after the superclass's __init__ method has been called.
+ """
+ for attr in filter(lambda k: hasattr(self, k), self.removedAttrs):
+ delattr(self, attr)
diff --git a/scripts/lib/wic/3rdparty/pykickstart/commands/__init__.py b/scripts/lib/wic/3rdparty/pykickstart/commands/__init__.py
new file mode 100644
index 0000000000..2d94550935
--- /dev/null
+++ b/scripts/lib/wic/3rdparty/pykickstart/commands/__init__.py
@@ -0,0 +1,20 @@
+#
+# Chris Lumens <clumens@redhat.com>
+#
+# Copyright 2009 Red Hat, Inc.
+#
+# This copyrighted material is made available to anyone wishing to use, modify,
+# copy, or redistribute it subject to the terms and conditions of the GNU
+# General Public License v.2. This program is distributed in the hope that it
+# will be useful, but WITHOUT ANY WARRANTY expressed or implied, including the
+# implied warranties of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# See the GNU General Public License for more details.
+#
+# 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., 51
+# Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. Any Red Hat
+# trademarks that are incorporated in the source code or documentation are not
+# subject to the GNU General Public License and may only be used or replicated
+# with the express permission of Red Hat, Inc.
+#
+import bootloader, partition
diff --git a/scripts/lib/wic/3rdparty/pykickstart/commands/bootloader.py b/scripts/lib/wic/3rdparty/pykickstart/commands/bootloader.py
new file mode 100644
index 0000000000..c2b552f689
--- /dev/null
+++ b/scripts/lib/wic/3rdparty/pykickstart/commands/bootloader.py
@@ -0,0 +1,216 @@
+#
+# Chris Lumens <clumens@redhat.com>
+#
+# Copyright 2007 Red Hat, Inc.
+#
+# This copyrighted material is made available to anyone wishing to use, modify,
+# copy, or redistribute it subject to the terms and conditions of the GNU
+# General Public License v.2. This program is distributed in the hope that it
+# will be useful, but WITHOUT ANY WARRANTY expressed or implied, including the
+# implied warranties of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# See the GNU General Public License for more details.
+#
+# 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., 51
+# Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. Any Red Hat
+# trademarks that are incorporated in the source code or documentation are not
+# subject to the GNU General Public License and may only be used or replicated
+# with the express permission of Red Hat, Inc.
+#
+from pykickstart.base import *
+from pykickstart.options import *
+
+class FC3_Bootloader(KickstartCommand):
+ removedKeywords = KickstartCommand.removedKeywords
+ removedAttrs = KickstartCommand.removedAttrs
+
+ def __init__(self, writePriority=10, *args, **kwargs):
+ KickstartCommand.__init__(self, writePriority, *args, **kwargs)
+ self.op = self._getParser()
+
+ self.driveorder = kwargs.get("driveorder", [])
+ self.appendLine = kwargs.get("appendLine", "")
+ self.forceLBA = kwargs.get("forceLBA", False)
+ self.linear = kwargs.get("linear", True)
+ self.location = kwargs.get("location", "")
+ self.md5pass = kwargs.get("md5pass", "")
+ self.password = kwargs.get("password", "")
+ self.upgrade = kwargs.get("upgrade", False)
+ self.useLilo = kwargs.get("useLilo", False)
+
+ self.deleteRemovedAttrs()
+
+ def _getArgsAsStr(self):
+ retval = ""
+
+ if self.appendLine != "":
+ retval += " --append=\"%s\"" % self.appendLine
+ if self.linear:
+ retval += " --linear"
+ if self.location:
+ retval += " --location=%s" % self.location
+ if hasattr(self, "forceLBA") and self.forceLBA:
+ retval += " --lba32"
+ if self.password != "":
+ retval += " --password=\"%s\"" % self.password
+ if self.md5pass != "":
+ retval += " --md5pass=\"%s\"" % self.md5pass
+ if self.upgrade:
+ retval += " --upgrade"
+ if self.useLilo:
+ retval += " --useLilo"
+ if len(self.driveorder) > 0:
+ retval += " --driveorder=\"%s\"" % ",".join(self.driveorder)
+
+ return retval
+
+ def __str__(self):
+ retval = KickstartCommand.__str__(self)
+
+ if self.location != "":
+ retval += "# System bootloader configuration\nbootloader"
+ retval += self._getArgsAsStr() + "\n"
+
+ return retval
+
+ def _getParser(self):
+ def driveorder_cb (option, opt_str, value, parser):
+ for d in value.split(','):
+ parser.values.ensure_value(option.dest, []).append(d)
+
+ op = KSOptionParser()
+ op.add_option("--append", dest="appendLine")
+ op.add_option("--linear", dest="linear", action="store_true",
+ default=True)
+ op.add_option("--nolinear", dest="linear", action="store_false")
+ op.add_option("--location", dest="location", type="choice",
+ default="mbr",
+ choices=["mbr", "partition", "none", "boot"])
+ op.add_option("--lba32", dest="forceLBA", action="store_true",
+ default=False)
+ op.add_option("--password", dest="password", default="")
+ op.add_option("--md5pass", dest="md5pass", default="")
+ op.add_option("--upgrade", dest="upgrade", action="store_true",
+ default=False)
+ op.add_option("--useLilo", dest="useLilo", action="store_true",
+ default=False)
+ op.add_option("--driveorder", dest="driveorder", action="callback",
+ callback=driveorder_cb, nargs=1, type="string")
+ return op
+
+ def parse(self, args):
+ (opts, extra) = self.op.parse_args(args=args, lineno=self.lineno)
+ self._setToSelf(self.op, opts)
+
+ if self.currentCmd == "lilo":
+ self.useLilo = True
+
+ return self
+
+class FC4_Bootloader(FC3_Bootloader):
+ removedKeywords = FC3_Bootloader.removedKeywords + ["linear", "useLilo"]
+ removedAttrs = FC3_Bootloader.removedAttrs + ["linear", "useLilo"]
+
+ def __init__(self, writePriority=10, *args, **kwargs):
+ FC3_Bootloader.__init__(self, writePriority, *args, **kwargs)
+
+ def _getArgsAsStr(self):
+ retval = ""
+ if self.appendLine != "":
+ retval += " --append=\"%s\"" % self.appendLine
+ if self.location:
+ retval += " --location=%s" % self.location
+ if hasattr(self, "forceLBA") and self.forceLBA:
+ retval += " --lba32"
+ if self.password != "":
+ retval += " --password=\"%s\"" % self.password
+ if self.md5pass != "":
+ retval += " --md5pass=\"%s\"" % self.md5pass
+ if self.upgrade:
+ retval += " --upgrade"
+ if len(self.driveorder) > 0:
+ retval += " --driveorder=\"%s\"" % ",".join(self.driveorder)
+ return retval
+
+ def _getParser(self):
+ op = FC3_Bootloader._getParser(self)
+ op.remove_option("--linear")
+ op.remove_option("--nolinear")
+ op.remove_option("--useLilo")
+ return op
+
+ def parse(self, args):
+ (opts, extra) = self.op.parse_args(args=args, lineno=self.lineno)
+ self._setToSelf(self.op, opts)
+ return self
+
+class F8_Bootloader(FC4_Bootloader):
+ removedKeywords = FC4_Bootloader.removedKeywords
+ removedAttrs = FC4_Bootloader.removedAttrs
+
+ def __init__(self, writePriority=10, *args, **kwargs):
+ FC4_Bootloader.__init__(self, writePriority, *args, **kwargs)
+
+ self.timeout = kwargs.get("timeout", None)
+ self.default = kwargs.get("default", "")
+
+ def _getArgsAsStr(self):
+ ret = FC4_Bootloader._getArgsAsStr(self)
+
+ if self.timeout is not None:
+ ret += " --timeout=%d" %(self.timeout,)
+ if self.default:
+ ret += " --default=%s" %(self.default,)
+
+ return ret
+
+ def _getParser(self):
+ op = FC4_Bootloader._getParser(self)
+ op.add_option("--timeout", dest="timeout", type="int")
+ op.add_option("--default", dest="default")
+ return op
+
+class F12_Bootloader(F8_Bootloader):
+ removedKeywords = F8_Bootloader.removedKeywords
+ removedAttrs = F8_Bootloader.removedAttrs
+
+ def _getParser(self):
+ op = F8_Bootloader._getParser(self)
+ op.add_option("--lba32", dest="forceLBA", deprecated=1, action="store_true")
+ return op
+
+class F14_Bootloader(F12_Bootloader):
+ removedKeywords = F12_Bootloader.removedKeywords + ["forceLBA"]
+ removedAttrs = F12_Bootloader.removedKeywords + ["forceLBA"]
+
+ def _getParser(self):
+ op = F12_Bootloader._getParser(self)
+ op.remove_option("--lba32")
+ return op
+
+class F15_Bootloader(F14_Bootloader):
+ removedKeywords = F14_Bootloader.removedKeywords
+ removedAttrs = F14_Bootloader.removedAttrs
+
+ def __init__(self, writePriority=10, *args, **kwargs):
+ F14_Bootloader.__init__(self, writePriority, *args, **kwargs)
+
+ self.isCrypted = kwargs.get("isCrypted", False)
+
+ def _getArgsAsStr(self):
+ ret = F14_Bootloader._getArgsAsStr(self)
+
+ if self.isCrypted:
+ ret += " --iscrypted"
+
+ return ret
+
+ def _getParser(self):
+ def password_cb(option, opt_str, value, parser):
+ parser.values.isCrypted = True
+ parser.values.password = value
+
+ op = F14_Bootloader._getParser(self)
+ op.add_option("--iscrypted", dest="isCrypted", action="store_true", default=False)
+ op.add_option("--md5pass", action="callback", callback=password_cb, nargs=1, type="string")
+ return op
diff --git a/scripts/lib/wic/3rdparty/pykickstart/commands/partition.py b/scripts/lib/wic/3rdparty/pykickstart/commands/partition.py
new file mode 100644
index 0000000000..56b91aa9d9
--- /dev/null
+++ b/scripts/lib/wic/3rdparty/pykickstart/commands/partition.py
@@ -0,0 +1,314 @@
+#
+# Chris Lumens <clumens@redhat.com>
+#
+# Copyright 2005, 2006, 2007, 2008 Red Hat, Inc.
+#
+# This copyrighted material is made available to anyone wishing to use, modify,
+# copy, or redistribute it subject to the terms and conditions of the GNU
+# General Public License v.2. This program is distributed in the hope that it
+# will be useful, but WITHOUT ANY WARRANTY expressed or implied, including the
+# implied warranties of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# See the GNU General Public License for more details.
+#
+# 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., 51
+# Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. Any Red Hat
+# trademarks that are incorporated in the source code or documentation are not
+# subject to the GNU General Public License and may only be used or replicated
+# with the express permission of Red Hat, Inc.
+#
+from pykickstart.base import *
+from pykickstart.errors import *
+from pykickstart.options import *
+
+import gettext
+import warnings
+_ = lambda x: gettext.ldgettext("pykickstart", x)
+
+class FC3_PartData(BaseData):
+ removedKeywords = BaseData.removedKeywords
+ removedAttrs = BaseData.removedAttrs
+
+ def __init__(self, *args, **kwargs):
+ BaseData.__init__(self, *args, **kwargs)
+ self.active = kwargs.get("active", False)
+ self.primOnly = kwargs.get("primOnly", False)
+ self.end = kwargs.get("end", 0)
+ self.fstype = kwargs.get("fstype", "")
+ self.grow = kwargs.get("grow", False)
+ self.maxSizeMB = kwargs.get("maxSizeMB", 0)
+ self.format = kwargs.get("format", True)
+ self.onbiosdisk = kwargs.get("onbiosdisk", "")
+ self.disk = kwargs.get("disk", "")
+ self.onPart = kwargs.get("onPart", "")
+ self.recommended = kwargs.get("recommended", False)
+ self.size = kwargs.get("size", None)
+ self.start = kwargs.get("start", 0)
+ self.mountpoint = kwargs.get("mountpoint", "")
+
+ def __eq__(self, y):
+ if self.mountpoint:
+ return self.mountpoint == y.mountpoint
+ else:
+ return False
+
+ def _getArgsAsStr(self):
+ retval = ""
+
+ if self.active:
+ retval += " --active"
+ if self.primOnly:
+ retval += " --asprimary"
+ if hasattr(self, "end") and self.end != 0:
+ retval += " --end=%s" % self.end
+ if self.fstype != "":
+ retval += " --fstype=\"%s\"" % self.fstype
+ if self.grow:
+ retval += " --grow"
+ if self.maxSizeMB > 0:
+ retval += " --maxsize=%d" % self.maxSizeMB
+ if not self.format:
+ retval += " --noformat"
+ if self.onbiosdisk != "":
+ retval += " --onbiosdisk=%s" % self.onbiosdisk
+ if self.disk != "":
+ retval += " --ondisk=%s" % self.disk
+ if self.onPart != "":
+ retval += " --onpart=%s" % self.onPart
+ if self.recommended:
+ retval += " --recommended"
+ if self.size and self.size != 0:
+ retval += " --size=%s" % self.size
+ if hasattr(self, "start") and self.start != 0:
+ retval += " --start=%s" % self.start
+
+ return retval
+
+ def __str__(self):
+ retval = BaseData.__str__(self)
+ if self.mountpoint:
+ mountpoint_str = "%s" % self.mountpoint
+ else:
+ mountpoint_str = "(No mount point)"
+ retval += "part %s%s\n" % (mountpoint_str, self._getArgsAsStr())
+ return retval
+
+class FC4_PartData(FC3_PartData):
+ removedKeywords = FC3_PartData.removedKeywords
+ removedAttrs = FC3_PartData.removedAttrs
+
+ def __init__(self, *args, **kwargs):
+ FC3_PartData.__init__(self, *args, **kwargs)
+ self.bytesPerInode = kwargs.get("bytesPerInode", 4096)
+ self.fsopts = kwargs.get("fsopts", "")
+ self.label = kwargs.get("label", "")
+
+ def _getArgsAsStr(self):
+ retval = FC3_PartData._getArgsAsStr(self)
+
+ if hasattr(self, "bytesPerInode") and self.bytesPerInode != 0:
+ retval += " --bytes-per-inode=%d" % self.bytesPerInode
+ if self.fsopts != "":
+ retval += " --fsoptions=\"%s\"" % self.fsopts
+ if self.label != "":
+ retval += " --label=%s" % self.label
+
+ return retval
+
+class F9_PartData(FC4_PartData):
+ removedKeywords = FC4_PartData.removedKeywords + ["bytesPerInode"]
+ removedAttrs = FC4_PartData.removedAttrs + ["bytesPerInode"]
+
+ def __init__(self, *args, **kwargs):
+ FC4_PartData.__init__(self, *args, **kwargs)
+ self.deleteRemovedAttrs()
+
+ self.fsopts = kwargs.get("fsopts", "")
+ self.label = kwargs.get("label", "")
+ self.fsprofile = kwargs.get("fsprofile", "")
+ self.encrypted = kwargs.get("encrypted", False)
+ self.passphrase = kwargs.get("passphrase", "")
+
+ def _getArgsAsStr(self):
+ retval = FC4_PartData._getArgsAsStr(self)
+
+ if self.fsprofile != "":
+ retval += " --fsprofile=\"%s\"" % self.fsprofile
+ if self.encrypted:
+ retval += " --encrypted"
+
+ if self.passphrase != "":
+ retval += " --passphrase=\"%s\"" % self.passphrase
+
+ return retval
+
+class F11_PartData(F9_PartData):
+ removedKeywords = F9_PartData.removedKeywords + ["start", "end"]
+ removedAttrs = F9_PartData.removedAttrs + ["start", "end"]
+
+class F12_PartData(F11_PartData):
+ removedKeywords = F11_PartData.removedKeywords
+ removedAttrs = F11_PartData.removedAttrs
+
+ def __init__(self, *args, **kwargs):
+ F11_PartData.__init__(self, *args, **kwargs)
+
+ self.escrowcert = kwargs.get("escrowcert", "")
+ self.backuppassphrase = kwargs.get("backuppassphrase", False)
+
+ def _getArgsAsStr(self):
+ retval = F11_PartData._getArgsAsStr(self)
+
+ if self.encrypted and self.escrowcert != "":
+ retval += " --escrowcert=\"%s\"" % self.escrowcert
+
+ if self.backuppassphrase:
+ retval += " --backuppassphrase"
+
+ return retval
+
+F14_PartData = F12_PartData
+
+class FC3_Partition(KickstartCommand):
+ removedKeywords = KickstartCommand.removedKeywords
+ removedAttrs = KickstartCommand.removedAttrs
+
+ def __init__(self, writePriority=130, *args, **kwargs):
+ KickstartCommand.__init__(self, writePriority, *args, **kwargs)
+ self.op = self._getParser()
+
+ self.partitions = kwargs.get("partitions", [])
+
+ def __str__(self):
+ retval = ""
+
+ for part in self.partitions:
+ retval += part.__str__()
+
+ if retval != "":
+ return "# Disk partitioning information\n" + retval
+ else:
+ return ""
+
+ def _getParser(self):
+ def part_cb (option, opt_str, value, parser):
+ if value.startswith("/dev/"):
+ parser.values.ensure_value(option.dest, value[5:])
+ else:
+ parser.values.ensure_value(option.dest, value)
+
+ op = KSOptionParser()
+ op.add_option("--active", dest="active", action="store_true",
+ default=False)
+ op.add_option("--asprimary", dest="primOnly", action="store_true",
+ default=False)
+ op.add_option("--end", dest="end", action="store", type="int",
+ nargs=1)
+ op.add_option("--fstype", "--type", dest="fstype")
+ op.add_option("--grow", dest="grow", action="store_true", default=False)
+ op.add_option("--maxsize", dest="maxSizeMB", action="store", type="int",
+ nargs=1)
+ op.add_option("--noformat", dest="format", action="store_false",
+ default=True)
+ op.add_option("--onbiosdisk", dest="onbiosdisk")
+ op.add_option("--ondisk", "--ondrive", dest="disk")
+ op.add_option("--onpart", "--usepart", dest="onPart", action="callback",
+ callback=part_cb, nargs=1, type="string")
+ op.add_option("--recommended", dest="recommended", action="store_true",
+ default=False)
+ op.add_option("--size", dest="size", action="store", type="int",
+ nargs=1)
+ op.add_option("--start", dest="start", action="store", type="int",
+ nargs=1)
+ return op
+
+ def parse(self, args):
+ (opts, extra) = self.op.parse_args(args=args, lineno=self.lineno)
+
+ pd = self.handler.PartData()
+ self._setToObj(self.op, opts, pd)
+ pd.lineno = self.lineno
+ if extra:
+ pd.mountpoint = extra[0]
+ if pd in self.dataList():
+ warnings.warn(_("A partition with the mountpoint %s has already been defined.") % pd.mountpoint)
+ else:
+ pd.mountpoint = None
+
+ return pd
+
+ def dataList(self):
+ return self.partitions
+
+class FC4_Partition(FC3_Partition):
+ removedKeywords = FC3_Partition.removedKeywords
+ removedAttrs = FC3_Partition.removedAttrs
+
+ def __init__(self, writePriority=130, *args, **kwargs):
+ FC3_Partition.__init__(self, writePriority, *args, **kwargs)
+
+ def part_cb (option, opt_str, value, parser):
+ if value.startswith("/dev/"):
+ parser.values.ensure_value(option.dest, value[5:])
+ else:
+ parser.values.ensure_value(option.dest, value)
+
+ def _getParser(self):
+ op = FC3_Partition._getParser(self)
+ op.add_option("--bytes-per-inode", dest="bytesPerInode", action="store",
+ type="int", nargs=1)
+ op.add_option("--fsoptions", dest="fsopts")
+ op.add_option("--label", dest="label")
+ return op
+
+class F9_Partition(FC4_Partition):
+ removedKeywords = FC4_Partition.removedKeywords
+ removedAttrs = FC4_Partition.removedAttrs
+
+ def __init__(self, writePriority=130, *args, **kwargs):
+ FC4_Partition.__init__(self, writePriority, *args, **kwargs)
+
+ def part_cb (option, opt_str, value, parser):
+ if value.startswith("/dev/"):
+ parser.values.ensure_value(option.dest, value[5:])
+ else:
+ parser.values.ensure_value(option.dest, value)
+
+ def _getParser(self):
+ op = FC4_Partition._getParser(self)
+ op.add_option("--bytes-per-inode", deprecated=1)
+ op.add_option("--fsprofile")
+ op.add_option("--encrypted", action="store_true", default=False)
+ op.add_option("--passphrase")
+ return op
+
+class F11_Partition(F9_Partition):
+ removedKeywords = F9_Partition.removedKeywords
+ removedAttrs = F9_Partition.removedAttrs
+
+ def _getParser(self):
+ op = F9_Partition._getParser(self)
+ op.add_option("--start", deprecated=1)
+ op.add_option("--end", deprecated=1)
+ return op
+
+class F12_Partition(F11_Partition):
+ removedKeywords = F11_Partition.removedKeywords
+ removedAttrs = F11_Partition.removedAttrs
+
+ def _getParser(self):
+ op = F11_Partition._getParser(self)
+ op.add_option("--escrowcert")
+ op.add_option("--backuppassphrase", action="store_true", default=False)
+ return op
+
+class F14_Partition(F12_Partition):
+ removedKeywords = F12_Partition.removedKeywords
+ removedAttrs = F12_Partition.removedAttrs
+
+ def _getParser(self):
+ op = F12_Partition._getParser(self)
+ op.remove_option("--bytes-per-inode")
+ op.remove_option("--start")
+ op.remove_option("--end")
+ return op
diff --git a/scripts/lib/wic/3rdparty/pykickstart/constants.py b/scripts/lib/wic/3rdparty/pykickstart/constants.py
new file mode 100644
index 0000000000..5e12fc80ec
--- /dev/null
+++ b/scripts/lib/wic/3rdparty/pykickstart/constants.py
@@ -0,0 +1,57 @@
+#
+# Chris Lumens <clumens@redhat.com>
+#
+# Copyright 2005-2007 Red Hat, Inc.
+#
+# This copyrighted material is made available to anyone wishing to use, modify,
+# copy, or redistribute it subject to the terms and conditions of the GNU
+# General Public License v.2. This program is distributed in the hope that it
+# will be useful, but WITHOUT ANY WARRANTY expressed or implied, including the
+# implied warranties of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# See the GNU General Public License for more details.
+#
+# 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., 51
+# Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. Any Red Hat
+# trademarks that are incorporated in the source code or documentation are not
+# subject to the GNU General Public License and may only be used or replicated
+# with the express permission of Red Hat, Inc.
+#
+CLEARPART_TYPE_LINUX = 0
+CLEARPART_TYPE_ALL = 1
+CLEARPART_TYPE_NONE = 2
+
+DISPLAY_MODE_CMDLINE = 0
+DISPLAY_MODE_GRAPHICAL = 1
+DISPLAY_MODE_TEXT = 2
+
+FIRSTBOOT_DEFAULT = 0
+FIRSTBOOT_SKIP = 1
+FIRSTBOOT_RECONFIG = 2
+
+KS_MISSING_PROMPT = 0
+KS_MISSING_IGNORE = 1
+
+SELINUX_DISABLED = 0
+SELINUX_ENFORCING = 1
+SELINUX_PERMISSIVE = 2
+
+KS_SCRIPT_PRE = 0
+KS_SCRIPT_POST = 1
+KS_SCRIPT_TRACEBACK = 2
+
+KS_WAIT = 0
+KS_REBOOT = 1
+KS_SHUTDOWN = 2
+
+KS_INSTKEY_SKIP = -99
+
+BOOTPROTO_DHCP = "dhcp"
+BOOTPROTO_BOOTP = "bootp"
+BOOTPROTO_STATIC = "static"
+BOOTPROTO_QUERY = "query"
+BOOTPROTO_IBFT = "ibft"
+
+GROUP_REQUIRED = 0
+GROUP_DEFAULT = 1
+GROUP_ALL = 2
diff --git a/scripts/lib/wic/3rdparty/pykickstart/errors.py b/scripts/lib/wic/3rdparty/pykickstart/errors.py
new file mode 100644
index 0000000000..a234d99d43
--- /dev/null
+++ b/scripts/lib/wic/3rdparty/pykickstart/errors.py
@@ -0,0 +1,103 @@
+#
+# errors.py: Kickstart error handling.
+#
+# Chris Lumens <clumens@redhat.com>
+#
+# This copyrighted material is made available to anyone wishing to use, modify,
+# copy, or redistribute it subject to the terms and conditions of the GNU
+# General Public License v.2. This program is distributed in the hope that it
+# will be useful, but WITHOUT ANY WARRANTY expressed or implied, including the
+# implied warranties of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# See the GNU General Public License for more details.
+#
+# 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., 51
+# Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. Any Red Hat
+# trademarks that are incorporated in the source code or documentation are not
+# subject to the GNU General Public License and may only be used or replicated
+# with the express permission of Red Hat, Inc.
+#
+"""
+Error handling classes and functions.
+
+This module exports a single function:
+
+ formatErrorMsg - Properly formats an error message.
+
+It also exports several exception classes:
+
+ KickstartError - A generic exception class.
+
+ KickstartParseError - An exception for errors relating to parsing.
+
+ KickstartValueError - An exception for errors relating to option
+ processing.
+
+ KickstartVersionError - An exception for errors relating to unsupported
+ syntax versions.
+"""
+import gettext
+_ = lambda x: gettext.ldgettext("pykickstart", x)
+
+def formatErrorMsg(lineno, msg=""):
+ """Properly format the error message msg for inclusion in an exception."""
+ if msg != "":
+ mapping = {"lineno": lineno, "msg": msg}
+ return _("The following problem occurred on line %(lineno)s of the kickstart file:\n\n%(msg)s\n") % mapping
+ else:
+ return _("There was a problem reading from line %s of the kickstart file") % lineno
+
+class KickstartError(Exception):
+ """A generic exception class for unspecific error conditions."""
+ def __init__(self, val = ""):
+ """Create a new KickstartError exception instance with the descriptive
+ message val. val should be the return value of formatErrorMsg.
+ """
+ Exception.__init__(self)
+ self.value = val
+
+ def __str__ (self):
+ return self.value
+
+class KickstartParseError(KickstartError):
+ """An exception class for errors when processing the input file, such as
+ unknown options, commands, or sections.
+ """
+ def __init__(self, msg):
+ """Create a new KickstartParseError exception instance with the
+ descriptive message val. val should be the return value of
+ formatErrorMsg.
+ """
+ KickstartError.__init__(self, msg)
+
+ def __str__(self):
+ return self.value
+
+class KickstartValueError(KickstartError):
+ """An exception class for errors when processing arguments to commands,
+ such as too many arguments, too few arguments, or missing required
+ arguments.
+ """
+ def __init__(self, msg):
+ """Create a new KickstartValueError exception instance with the
+ descriptive message val. val should be the return value of
+ formatErrorMsg.
+ """
+ KickstartError.__init__(self, msg)
+
+ def __str__ (self):
+ return self.value
+
+class KickstartVersionError(KickstartError):
+ """An exception class for errors related to using an incorrect version of
+ kickstart syntax.
+ """
+ def __init__(self, msg):
+ """Create a new KickstartVersionError exception instance with the
+ descriptive message val. val should be the return value of
+ formatErrorMsg.
+ """
+ KickstartError.__init__(self, msg)
+
+ def __str__ (self):
+ return self.value
diff --git a/scripts/lib/wic/3rdparty/pykickstart/handlers/__init__.py b/scripts/lib/wic/3rdparty/pykickstart/handlers/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/scripts/lib/wic/3rdparty/pykickstart/handlers/__init__.py
diff --git a/scripts/lib/wic/3rdparty/pykickstart/handlers/control.py b/scripts/lib/wic/3rdparty/pykickstart/handlers/control.py
new file mode 100644
index 0000000000..8dc80d1ebe
--- /dev/null
+++ b/scripts/lib/wic/3rdparty/pykickstart/handlers/control.py
@@ -0,0 +1,46 @@
+#
+# Chris Lumens <clumens@redhat.com>
+#
+# Copyright 2007, 2008, 2009, 2010 Red Hat, Inc.
+#
+# This copyrighted material is made available to anyone wishing to use, modify,
+# copy, or redistribute it subject to the terms and conditions of the GNU
+# General Public License v.2. This program is distributed in the hope that it
+# will be useful, but WITHOUT ANY WARRANTY expressed or implied, including the
+# implied warranties of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# See the GNU General Public License for more details.
+#
+# 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., 51
+# Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. Any Red Hat
+# trademarks that are incorporated in the source code or documentation are not
+# subject to the GNU General Public License and may only be used or replicated
+# with the express permission of Red Hat, Inc.
+#
+from pykickstart.version import *
+from pykickstart.commands import *
+
+# This map is keyed on kickstart syntax version as provided by
+# pykickstart.version. Within each sub-dict is a mapping from command name
+# to the class that handles it. This is an onto mapping - that is, multiple
+# command names can map to the same class. However, the Handler will ensure
+# that only one instance of each class ever exists.
+commandMap = {
+ # based on f15
+ F16: {
+ "bootloader": bootloader.F15_Bootloader,
+ "part": partition.F14_Partition,
+ "partition": partition.F14_Partition,
+ },
+}
+
+# This map is keyed on kickstart syntax version as provided by
+# pykickstart.version. Within each sub-dict is a mapping from a data object
+# name to the class that provides it. This is a bijective mapping - that is,
+# each name maps to exactly one data class and all data classes have a name.
+# More than one instance of each class is allowed to exist, however.
+dataMap = {
+ F16: {
+ "PartData": partition.F14_PartData,
+ },
+}
diff --git a/scripts/lib/wic/3rdparty/pykickstart/handlers/f16.py b/scripts/lib/wic/3rdparty/pykickstart/handlers/f16.py
new file mode 100644
index 0000000000..3c52f8d754
--- /dev/null
+++ b/scripts/lib/wic/3rdparty/pykickstart/handlers/f16.py
@@ -0,0 +1,24 @@
+#
+# Chris Lumens <clumens@redhat.com>
+#
+# Copyright 2011 Red Hat, Inc.
+#
+# This copyrighted material is made available to anyone wishing to use, modify,
+# copy, or redistribute it subject to the terms and conditions of the GNU
+# General Public License v.2. This program is distributed in the hope that it
+# will be useful, but WITHOUT ANY WARRANTY expressed or implied, including the
+# implied warranties of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# See the GNU General Public License for more details.
+#
+# 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., 51
+# Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. Any Red Hat
+# trademarks that are incorporated in the source code or documentation are not
+# subject to the GNU General Public License and may only be used or replicated
+# with the express permission of Red Hat, Inc.
+#
+from pykickstart.base import *
+from pykickstart.version import *
+
+class F16Handler(BaseHandler):
+ version = F16
diff --git a/scripts/lib/wic/3rdparty/pykickstart/ko.py b/scripts/lib/wic/3rdparty/pykickstart/ko.py
new file mode 100644
index 0000000000..1350d19c70
--- /dev/null
+++ b/scripts/lib/wic/3rdparty/pykickstart/ko.py
@@ -0,0 +1,37 @@
+#
+# Chris Lumens <clumens@redhat.com>
+#
+# Copyright 2009 Red Hat, Inc.
+#
+# This copyrighted material is made available to anyone wishing to use, modify,
+# copy, or redistribute it subject to the terms and conditions of the GNU
+# General Public License v.2. This program is distributed in the hope that it
+# will be useful, but WITHOUT ANY WARRANTY expressed or implied, including the
+# implied warranties of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# See the GNU General Public License for more details.
+#
+# 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., 51
+# Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. Any Red Hat
+# trademarks that are incorporated in the source code or documentation are not
+# subject to the GNU General Public License and may only be used or replicated
+# with the express permission of Red Hat, Inc.
+#
+"""
+Base classes for internal pykickstart use.
+
+The module exports the following important classes:
+
+ KickstartObject - The base class for all classes in pykickstart
+"""
+
+class KickstartObject(object):
+ """The base class for all other classes in pykickstart."""
+ def __init__(self, *args, **kwargs):
+ """Create a new KickstartObject instance. All other classes in
+ pykickstart should be derived from this one. Instance attributes:
+ """
+ pass
+
+ def __str__(self):
+ return ""
diff --git a/scripts/lib/wic/3rdparty/pykickstart/options.py b/scripts/lib/wic/3rdparty/pykickstart/options.py
new file mode 100644
index 0000000000..341c5d7298
--- /dev/null
+++ b/scripts/lib/wic/3rdparty/pykickstart/options.py
@@ -0,0 +1,204 @@
+#
+# Chris Lumens <clumens@redhat.com>
+#
+# Copyright 2005, 2006, 2007 Red Hat, Inc.
+#
+# This copyrighted material is made available to anyone wishing to use, modify,
+# copy, or redistribute it subject to the terms and conditions of the GNU
+# General Public License v.2. This program is distributed in the hope that it
+# will be useful, but WITHOUT ANY WARRANTY expressed or implied, including the
+# implied warranties of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# See the GNU General Public License for more details.
+#
+# 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., 51
+# Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. Any Red Hat
+# trademarks that are incorporated in the source code or documentation are not
+# subject to the GNU General Public License and may only be used or replicated
+# with the express permission of Red Hat, Inc.
+#
+"""
+Specialized option handling.
+
+This module exports two classes:
+
+ KSOptionParser - A specialized subclass of OptionParser to be used
+ in BaseHandler subclasses.
+
+ KSOption - A specialized subclass of Option.
+"""
+import warnings
+from copy import copy
+from optparse import *
+
+from constants import *
+from errors import *
+from version import *
+
+import gettext
+_ = lambda x: gettext.ldgettext("pykickstart", x)
+
+class KSOptionParser(OptionParser):
+ """A specialized subclass of optparse.OptionParser to handle extra option
+ attribute checking, work error reporting into the KickstartParseError
+ framework, and to turn off the default help.
+ """
+ def exit(self, status=0, msg=None):
+ pass
+
+ def error(self, msg):
+ if self.lineno != None:
+ raise KickstartParseError, formatErrorMsg(self.lineno, msg=msg)
+ else:
+ raise KickstartParseError, msg
+
+ def keys(self):
+ retval = []
+
+ for opt in self.option_list:
+ if opt not in retval:
+ retval.append(opt.dest)
+
+ return retval
+
+ def _init_parsing_state (self):
+ OptionParser._init_parsing_state(self)
+ self.option_seen = {}
+
+ def check_values (self, values, args):
+ def seen(self, option):
+ return self.option_seen.has_key(option)
+
+ def usedTooNew(self, option):
+ return option.introduced and option.introduced > self.version
+
+ def usedDeprecated(self, option):
+ return option.deprecated
+
+ def usedRemoved(self, option):
+ return option.removed and option.removed <= self.version
+
+ for option in filter(lambda o: isinstance(o, Option), self.option_list):
+ if option.required and not seen(self, option):
+ raise KickstartValueError, formatErrorMsg(self.lineno, _("Option %s is required") % option)
+ elif seen(self, option) and usedTooNew(self, option):
+ mapping = {"option": option, "intro": versionToString(option.introduced),
+ "version": versionToString(self.version)}
+ self.error(_("The %(option)s option was introduced in version %(intro)s, but you are using kickstart syntax version %(version)s.") % mapping)
+ elif seen(self, option) and usedRemoved(self, option):
+ mapping = {"option": option, "removed": versionToString(option.removed),
+ "version": versionToString(self.version)}
+
+ if option.removed == self.version:
+ self.error(_("The %(option)s option is no longer supported.") % mapping)
+ else:
+ self.error(_("The %(option)s option was removed in version %(removed)s, but you are using kickstart syntax version %(version)s.") % mapping)
+ elif seen(self, option) and usedDeprecated(self, option):
+ mapping = {"lineno": self.lineno, "option": option}
+ warnings.warn(_("Ignoring deprecated option on line %(lineno)s: The %(option)s option has been deprecated and no longer has any effect. It may be removed from future releases, which will result in a fatal error from kickstart. Please modify your kickstart file to remove this option.") % mapping, DeprecationWarning)
+
+ return (values, args)
+
+ def parse_args(self, *args, **kwargs):
+ if kwargs.has_key("lineno"):
+ self.lineno = kwargs.pop("lineno")
+
+ return OptionParser.parse_args(self, **kwargs)
+
+ def __init__(self, mapping=None, version=None):
+ """Create a new KSOptionParser instance. Each KickstartCommand
+ subclass should create one instance of KSOptionParser, providing
+ at least the lineno attribute. mapping and version are not required.
+ Instance attributes:
+
+ mapping -- A mapping from option strings to different values.
+ version -- The version of the kickstart syntax we are checking
+ against.
+ """
+ OptionParser.__init__(self, option_class=KSOption,
+ add_help_option=False,
+ conflict_handler="resolve")
+ if mapping is None:
+ self.map = {}
+ else:
+ self.map = mapping
+
+ self.lineno = None
+ self.option_seen = {}
+ self.version = version
+
+def _check_ksboolean(option, opt, value):
+ if value.lower() in ("on", "yes", "true", "1"):
+ return True
+ elif value.lower() in ("off", "no", "false", "0"):
+ return False
+ else:
+ mapping = {"opt": opt, "value": value}
+ raise OptionValueError(_("Option %(opt)s: invalid boolean value: %(value)r") % mapping)
+
+def _check_string(option, opt, value):
+ if len(value) > 2 and value.startswith("--"):
+ mapping = {"opt": opt, "value": value}
+ raise OptionValueError(_("Option %(opt)s: invalid string value: %(value)r") % mapping)
+ else:
+ return value
+
+# Creates a new Option class that supports several new attributes:
+# - required: any option with this attribute must be supplied or an exception
+# is thrown
+# - introduced: the kickstart syntax version that this option first appeared
+# in - an exception will be raised if the option is used and
+# the specified syntax version is less than the value of this
+# attribute
+# - deprecated: the kickstart syntax version that this option was deprecated
+# in - a DeprecationWarning will be thrown if the option is
+# used and the specified syntax version is greater than the
+# value of this attribute
+# - removed: the kickstart syntax version that this option was removed in - an
+# exception will be raised if the option is used and the specified
+# syntax version is greated than the value of this attribute
+# Also creates a new type:
+# - ksboolean: support various kinds of boolean values on an option
+# And two new actions:
+# - map : allows you to define an opt -> val mapping such that dest gets val
+# when opt is seen
+# - map_extend: allows you to define an opt -> [val1, ... valn] mapping such
+# that dest gets a list of vals built up when opt is seen
+class KSOption (Option):
+ ATTRS = Option.ATTRS + ['introduced', 'deprecated', 'removed', 'required']
+ ACTIONS = Option.ACTIONS + ("map", "map_extend",)
+ STORE_ACTIONS = Option.STORE_ACTIONS + ("map", "map_extend",)
+
+ TYPES = Option.TYPES + ("ksboolean", "string")
+ TYPE_CHECKER = copy(Option.TYPE_CHECKER)
+ TYPE_CHECKER["ksboolean"] = _check_ksboolean
+ TYPE_CHECKER["string"] = _check_string
+
+ def _check_required(self):
+ if self.required and not self.takes_value():
+ raise OptionError(_("Required flag set for option that doesn't take a value"), self)
+
+ # Make sure _check_required() is called from the constructor!
+ CHECK_METHODS = Option.CHECK_METHODS + [_check_required]
+
+ def process (self, opt, value, values, parser):
+ Option.process(self, opt, value, values, parser)
+ parser.option_seen[self] = 1
+
+ # Override default take_action method to handle our custom actions.
+ def take_action(self, action, dest, opt, value, values, parser):
+ if action == "map":
+ values.ensure_value(dest, parser.map[opt.lstrip('-')])
+ elif action == "map_extend":
+ values.ensure_value(dest, []).extend(parser.map[opt.lstrip('-')])
+ else:
+ Option.take_action(self, action, dest, opt, value, values, parser)
+
+ def takes_value(self):
+ # Deprecated options don't take a value.
+ return Option.takes_value(self) and not self.deprecated
+
+ def __init__(self, *args, **kwargs):
+ self.deprecated = False
+ self.required = False
+ Option.__init__(self, *args, **kwargs)
diff --git a/scripts/lib/wic/3rdparty/pykickstart/parser.py b/scripts/lib/wic/3rdparty/pykickstart/parser.py
new file mode 100644
index 0000000000..840a448673
--- /dev/null
+++ b/scripts/lib/wic/3rdparty/pykickstart/parser.py
@@ -0,0 +1,702 @@
+#
+# parser.py: Kickstart file parser.
+#
+# Chris Lumens <clumens@redhat.com>
+#
+# Copyright 2005, 2006, 2007, 2008, 2011 Red Hat, Inc.
+#
+# This copyrighted material is made available to anyone wishing to use, modify,
+# copy, or redistribute it subject to the terms and conditions of the GNU
+# General Public License v.2. This program is distributed in the hope that it
+# will be useful, but WITHOUT ANY WARRANTY expressed or implied, including the
+# implied warranties of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# See the GNU General Public License for more details.
+#
+# 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., 51
+# Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. Any Red Hat
+# trademarks that are incorporated in the source code or documentation are not
+# subject to the GNU General Public License and may only be used or replicated
+# with the express permission of Red Hat, Inc.
+#
+"""
+Main kickstart file processing module.
+
+This module exports several important classes:
+
+ Script - Representation of a single %pre, %post, or %traceback script.
+
+ Packages - Representation of the %packages section.
+
+ KickstartParser - The kickstart file parser state machine.
+"""
+
+from collections import Iterator
+import os
+import shlex
+import sys
+import tempfile
+from copy import copy
+from optparse import *
+from urlgrabber import urlread
+import urlgrabber.grabber as grabber
+
+import constants
+from errors import KickstartError, KickstartParseError, KickstartValueError, formatErrorMsg
+from ko import KickstartObject
+from sections import *
+import version
+
+import gettext
+_ = lambda x: gettext.ldgettext("pykickstart", x)
+
+STATE_END = "end"
+STATE_COMMANDS = "commands"
+
+ver = version.DEVEL
+
+def _preprocessStateMachine (lineIter):
+ l = None
+ lineno = 0
+
+ # Now open an output kickstart file that we are going to write to one
+ # line at a time.
+ (outF, outName) = tempfile.mkstemp("-ks.cfg", "", "/tmp")
+
+ while True:
+ try:
+ l = lineIter.next()
+ except StopIteration:
+ break
+
+ # At the end of the file?
+ if l == "":
+ break
+
+ lineno += 1
+ url = None
+
+ ll = l.strip()
+ if not ll.startswith("%ksappend"):
+ os.write(outF, l)
+ continue
+
+ # Try to pull down the remote file.
+ try:
+ ksurl = ll.split(' ')[1]
+ except:
+ raise KickstartParseError, formatErrorMsg(lineno, msg=_("Illegal url for %%ksappend: %s") % ll)
+
+ try:
+ url = grabber.urlopen(ksurl)
+ except grabber.URLGrabError, e:
+ raise KickstartError, formatErrorMsg(lineno, msg=_("Unable to open %%ksappend file: %s") % e.strerror)
+ else:
+ # Sanity check result. Sometimes FTP doesn't catch a file
+ # is missing.
+ try:
+ if url.size < 1:
+ raise KickstartError, formatErrorMsg(lineno, msg=_("Unable to open %%ksappend file"))
+ except:
+ raise KickstartError, formatErrorMsg(lineno, msg=_("Unable to open %%ksappend file"))
+
+ # If that worked, write the remote file to the output kickstart
+ # file in one burst. Then close everything up to get ready to
+ # read ahead in the input file. This allows multiple %ksappend
+ # lines to exist.
+ if url is not None:
+ os.write(outF, url.read())
+ url.close()
+
+ # All done - close the temp file and return its location.
+ os.close(outF)
+ return outName
+
+def preprocessFromString (s):
+ """Preprocess the kickstart file, provided as the string str. This
+ method is currently only useful for handling %ksappend lines,
+ which need to be fetched before the real kickstart parser can be
+ run. Returns the location of the complete kickstart file.
+ """
+ i = iter(s.splitlines(True) + [""])
+ rc = _preprocessStateMachine (i.next)
+ return rc
+
+def preprocessKickstart (f):
+ """Preprocess the kickstart file, given by the filename file. This
+ method is currently only useful for handling %ksappend lines,
+ which need to be fetched before the real kickstart parser can be
+ run. Returns the location of the complete kickstart file.
+ """
+ try:
+ fh = urlopen(f)
+ except grabber.URLGrabError, e:
+ raise KickstartError, formatErrorMsg(0, msg=_("Unable to open input kickstart file: %s") % e.strerror)
+
+ rc = _preprocessStateMachine (iter(fh.readlines()))
+ fh.close()
+ return rc
+
+class PutBackIterator(Iterator):
+ def __init__(self, iterable):
+ self._iterable = iter(iterable)
+ self._buf = None
+
+ def __iter__(self):
+ return self
+
+ def put(self, s):
+ self._buf = s
+
+ def next(self):
+ if self._buf:
+ retval = self._buf
+ self._buf = None
+ return retval
+ else:
+ return self._iterable.next()
+
+###
+### SCRIPT HANDLING
+###
+class Script(KickstartObject):
+ """A class representing a single kickstart script. If functionality beyond
+ just a data representation is needed (for example, a run method in
+ anaconda), Script may be subclassed. Although a run method is not
+ provided, most of the attributes of Script have to do with running the
+ script. Instances of Script are held in a list by the Version object.
+ """
+ def __init__(self, script, *args , **kwargs):
+ """Create a new Script instance. Instance attributes:
+
+ errorOnFail -- If execution of the script fails, should anaconda
+ stop, display an error, and then reboot without
+ running any other scripts?
+ inChroot -- Does the script execute in anaconda's chroot
+ environment or not?
+ interp -- The program that should be used to interpret this
+ script.
+ lineno -- The line number this script starts on.
+ logfile -- Where all messages from the script should be logged.
+ script -- A string containing all the lines of the script.
+ type -- The type of the script, which can be KS_SCRIPT_* from
+ pykickstart.constants.
+ """
+ KickstartObject.__init__(self, *args, **kwargs)
+ self.script = "".join(script)
+
+ self.interp = kwargs.get("interp", "/bin/sh")
+ self.inChroot = kwargs.get("inChroot", False)
+ self.lineno = kwargs.get("lineno", None)
+ self.logfile = kwargs.get("logfile", None)
+ self.errorOnFail = kwargs.get("errorOnFail", False)
+ self.type = kwargs.get("type", constants.KS_SCRIPT_PRE)
+
+ def __str__(self):
+ """Return a string formatted for output to a kickstart file."""
+ retval = ""
+
+ if self.type == constants.KS_SCRIPT_PRE:
+ retval += '\n%pre'
+ elif self.type == constants.KS_SCRIPT_POST:
+ retval += '\n%post'
+ elif self.type == constants.KS_SCRIPT_TRACEBACK:
+ retval += '\n%traceback'
+
+ if self.interp != "/bin/sh" and self.interp != "":
+ retval += " --interpreter=%s" % self.interp
+ if self.type == constants.KS_SCRIPT_POST and not self.inChroot:
+ retval += " --nochroot"
+ if self.logfile != None:
+ retval += " --logfile %s" % self.logfile
+ if self.errorOnFail:
+ retval += " --erroronfail"
+
+ if self.script.endswith("\n"):
+ if ver >= version.F8:
+ return retval + "\n%s%%end\n" % self.script
+ else:
+ return retval + "\n%s\n" % self.script
+ else:
+ if ver >= version.F8:
+ return retval + "\n%s\n%%end\n" % self.script
+ else:
+ return retval + "\n%s\n" % self.script
+
+
+##
+## PACKAGE HANDLING
+##
+class Group:
+ """A class representing a single group in the %packages section."""
+ def __init__(self, name="", include=constants.GROUP_DEFAULT):
+ """Create a new Group instance. Instance attributes:
+
+ name -- The group's identifier
+ include -- The level of how much of the group should be included.
+ Values can be GROUP_* from pykickstart.constants.
+ """
+ self.name = name
+ self.include = include
+
+ def __str__(self):
+ """Return a string formatted for output to a kickstart file."""
+ if self.include == constants.GROUP_REQUIRED:
+ return "@%s --nodefaults" % self.name
+ elif self.include == constants.GROUP_ALL:
+ return "@%s --optional" % self.name
+ else:
+ return "@%s" % self.name
+
+ def __cmp__(self, other):
+ if self.name < other.name:
+ return -1
+ elif self.name > other.name:
+ return 1
+ return 0
+
+class Packages(KickstartObject):
+ """A class representing the %packages section of the kickstart file."""
+ def __init__(self, *args, **kwargs):
+ """Create a new Packages instance. Instance attributes:
+
+ addBase -- Should the Base group be installed even if it is
+ not specified?
+ default -- Should the default package set be selected?
+ excludedList -- A list of all the packages marked for exclusion in
+ the %packages section, without the leading minus
+ symbol.
+ excludeDocs -- Should documentation in each package be excluded?
+ groupList -- A list of Group objects representing all the groups
+ specified in the %packages section. Names will be
+ stripped of the leading @ symbol.
+ excludedGroupList -- A list of Group objects representing all the
+ groups specified for removal in the %packages
+ section. Names will be stripped of the leading
+ -@ symbols.
+ handleMissing -- If unknown packages are specified in the %packages
+ section, should it be ignored or not? Values can
+ be KS_MISSING_* from pykickstart.constants.
+ packageList -- A list of all the packages specified in the
+ %packages section.
+ instLangs -- A list of languages to install.
+ """
+ KickstartObject.__init__(self, *args, **kwargs)
+
+ self.addBase = True
+ self.default = False
+ self.excludedList = []
+ self.excludedGroupList = []
+ self.excludeDocs = False
+ self.groupList = []
+ self.handleMissing = constants.KS_MISSING_PROMPT
+ self.packageList = []
+ self.instLangs = None
+
+ def __str__(self):
+ """Return a string formatted for output to a kickstart file."""
+ pkgs = ""
+
+ if not self.default:
+ grps = self.groupList
+ grps.sort()
+ for grp in grps:
+ pkgs += "%s\n" % grp.__str__()
+
+ p = self.packageList
+ p.sort()
+ for pkg in p:
+ pkgs += "%s\n" % pkg
+
+ grps = self.excludedGroupList
+ grps.sort()
+ for grp in grps:
+ pkgs += "-%s\n" % grp.__str__()
+
+ p = self.excludedList
+ p.sort()
+ for pkg in p:
+ pkgs += "-%s\n" % pkg
+
+ if pkgs == "":
+ return ""
+
+ retval = "\n%packages"
+
+ if self.default:
+ retval += " --default"
+ if self.excludeDocs:
+ retval += " --excludedocs"
+ if not self.addBase:
+ retval += " --nobase"
+ if self.handleMissing == constants.KS_MISSING_IGNORE:
+ retval += " --ignoremissing"
+ if self.instLangs:
+ retval += " --instLangs=%s" % self.instLangs
+
+ if ver >= version.F8:
+ return retval + "\n" + pkgs + "\n%end\n"
+ else:
+ return retval + "\n" + pkgs + "\n"
+
+ def _processGroup (self, line):
+ op = OptionParser()
+ op.add_option("--nodefaults", action="store_true", default=False)
+ op.add_option("--optional", action="store_true", default=False)
+
+ (opts, extra) = op.parse_args(args=line.split())
+
+ if opts.nodefaults and opts.optional:
+ raise KickstartValueError, _("Group cannot specify both --nodefaults and --optional")
+
+ # If the group name has spaces in it, we have to put it back together
+ # now.
+ grp = " ".join(extra)
+
+ if opts.nodefaults:
+ self.groupList.append(Group(name=grp, include=constants.GROUP_REQUIRED))
+ elif opts.optional:
+ self.groupList.append(Group(name=grp, include=constants.GROUP_ALL))
+ else:
+ self.groupList.append(Group(name=grp, include=constants.GROUP_DEFAULT))
+
+ def add (self, pkgList):
+ """Given a list of lines from the input file, strip off any leading
+ symbols and add the result to the appropriate list.
+ """
+ existingExcludedSet = set(self.excludedList)
+ existingPackageSet = set(self.packageList)
+ newExcludedSet = set()
+ newPackageSet = set()
+
+ excludedGroupList = []
+
+ for pkg in pkgList:
+ stripped = pkg.strip()
+
+ if stripped[0] == "@":
+ self._processGroup(stripped[1:])
+ elif stripped[0] == "-":
+ if stripped[1] == "@":
+ excludedGroupList.append(Group(name=stripped[2:]))
+ else:
+ newExcludedSet.add(stripped[1:])
+ else:
+ newPackageSet.add(stripped)
+
+ # Groups have to be excluded in two different ways (note: can't use
+ # sets here because we have to store objects):
+ excludedGroupNames = map(lambda g: g.name, excludedGroupList)
+
+ # First, an excluded group may be cancelling out a previously given
+ # one. This is often the case when using %include. So there we should
+ # just remove the group from the list.
+ self.groupList = filter(lambda g: g.name not in excludedGroupNames, self.groupList)
+
+ # Second, the package list could have included globs which are not
+ # processed by pykickstart. In that case we need to preserve a list of
+ # excluded groups so whatever tool doing package/group installation can
+ # take appropriate action.
+ self.excludedGroupList.extend(excludedGroupList)
+
+ existingPackageSet = (existingPackageSet - newExcludedSet) | newPackageSet
+ existingExcludedSet = (existingExcludedSet - existingPackageSet) | newExcludedSet
+
+ self.packageList = list(existingPackageSet)
+ self.excludedList = list(existingExcludedSet)
+
+
+###
+### PARSER
+###
+class KickstartParser:
+ """The kickstart file parser class as represented by a basic state
+ machine. To create a specialized parser, make a subclass and override
+ any of the methods you care about. Methods that don't need to do
+ anything may just pass. However, _stateMachine should never be
+ overridden.
+ """
+ def __init__ (self, handler, followIncludes=True, errorsAreFatal=True,
+ missingIncludeIsFatal=True):
+ """Create a new KickstartParser instance. Instance attributes:
+
+ errorsAreFatal -- Should errors cause processing to halt, or
+ just print a message to the screen? This
+ is most useful for writing syntax checkers
+ that may want to continue after an error is
+ encountered.
+ followIncludes -- If %include is seen, should the included
+ file be checked as well or skipped?
+ handler -- An instance of a BaseHandler subclass. If
+ None, the input file will still be parsed
+ but no data will be saved and no commands
+ will be executed.
+ missingIncludeIsFatal -- Should missing include files be fatal, even
+ if errorsAreFatal is False?
+ """
+ self.errorsAreFatal = errorsAreFatal
+ self.followIncludes = followIncludes
+ self.handler = handler
+ self.currentdir = {}
+ self.missingIncludeIsFatal = missingIncludeIsFatal
+
+ self._state = STATE_COMMANDS
+ self._includeDepth = 0
+ self._line = ""
+
+ self.version = self.handler.version
+
+ global ver
+ ver = self.version
+
+ self._sections = {}
+ self.setupSections()
+
+ def _reset(self):
+ """Reset the internal variables of the state machine for a new kickstart file."""
+ self._state = STATE_COMMANDS
+ self._includeDepth = 0
+
+ def getSection(self, s):
+ """Return a reference to the requested section (s must start with '%'s),
+ or raise KeyError if not found.
+ """
+ return self._sections[s]
+
+ def handleCommand (self, lineno, args):
+ """Given the list of command and arguments, call the Version's
+ dispatcher method to handle the command. Returns the command or
+ data object returned by the dispatcher. This method may be
+ overridden in a subclass if necessary.
+ """
+ if self.handler:
+ self.handler.currentCmd = args[0]
+ self.handler.currentLine = self._line
+ retval = self.handler.dispatcher(args, lineno)
+
+ return retval
+
+ def registerSection(self, obj):
+ """Given an instance of a Section subclass, register the new section
+ with the parser. Calling this method means the parser will
+ recognize your new section and dispatch into the given object to
+ handle it.
+ """
+ if not obj.sectionOpen:
+ raise TypeError, "no sectionOpen given for section %s" % obj
+
+ if not obj.sectionOpen.startswith("%"):
+ raise TypeError, "section %s tag does not start with a %%" % obj.sectionOpen
+
+ self._sections[obj.sectionOpen] = obj
+
+ def _finalize(self, obj):
+ """Called at the close of a kickstart section to take any required
+ actions. Internally, this is used to add scripts once we have the
+ whole body read.
+ """
+ obj.finalize()
+ self._state = STATE_COMMANDS
+
+ def _handleSpecialComments(self, line):
+ """Kickstart recognizes a couple special comments."""
+ if self._state != STATE_COMMANDS:
+ return
+
+ # Save the platform for s-c-kickstart.
+ if line[:10] == "#platform=":
+ self.handler.platform = self._line[11:]
+
+ def _readSection(self, lineIter, lineno):
+ obj = self._sections[self._state]
+
+ while True:
+ try:
+ line = lineIter.next()
+ if line == "":
+ # This section ends at the end of the file.
+ if self.version >= version.F8:
+ raise KickstartParseError, formatErrorMsg(lineno, msg=_("Section does not end with %%end."))
+
+ self._finalize(obj)
+ except StopIteration:
+ break
+
+ lineno += 1
+
+ # Throw away blank lines and comments, unless the section wants all
+ # lines.
+ if self._isBlankOrComment(line) and not obj.allLines:
+ continue
+
+ if line.startswith("%"):
+ args = shlex.split(line)
+
+ if args and args[0] == "%end":
+ # This is a properly terminated section.
+ self._finalize(obj)
+ break
+ elif args and args[0] == "%ksappend":
+ continue
+ elif args and (self._validState(args[0]) or args[0] in ["%include", "%ksappend"]):
+ # This is an unterminated section.
+ if self.version >= version.F8:
+ raise KickstartParseError, formatErrorMsg(lineno, msg=_("Section does not end with %%end."))
+
+ # Finish up. We do not process the header here because
+ # kicking back out to STATE_COMMANDS will ensure that happens.
+ lineIter.put(line)
+ lineno -= 1
+ self._finalize(obj)
+ break
+ else:
+ # This is just a line within a section. Pass it off to whatever
+ # section handles it.
+ obj.handleLine(line)
+
+ return lineno
+
+ def _validState(self, st):
+ """Is the given section tag one that has been registered with the parser?"""
+ return st in self._sections.keys()
+
+ def _tryFunc(self, fn):
+ """Call the provided function (which doesn't take any arguments) and
+ do the appropriate error handling. If errorsAreFatal is False, this
+ function will just print the exception and keep going.
+ """
+ try:
+ fn()
+ except Exception, msg:
+ if self.errorsAreFatal:
+ raise
+ else:
+ print msg
+
+ def _isBlankOrComment(self, line):
+ return line.isspace() or line == "" or line.lstrip()[0] == '#'
+
+ def _stateMachine(self, lineIter):
+ # For error reporting.
+ lineno = 0
+
+ while True:
+ # Get the next line out of the file, quitting if this is the last line.
+ try:
+ self._line = lineIter.next()
+ if self._line == "":
+ break
+ except StopIteration:
+ break
+
+ lineno += 1
+
+ # Eliminate blank lines, whitespace-only lines, and comments.
+ if self._isBlankOrComment(self._line):
+ self._handleSpecialComments(self._line)
+ continue
+
+ # Remove any end-of-line comments.
+ sanitized = self._line.split("#")[0]
+
+ # Then split the line.
+ args = shlex.split(sanitized.rstrip())
+
+ if args[0] == "%include":
+ # This case comes up primarily in ksvalidator.
+ if not self.followIncludes:
+ continue
+
+ if len(args) == 1 or not args[1]:
+ raise KickstartParseError, formatErrorMsg(lineno)
+
+ self._includeDepth += 1
+
+ try:
+ self.readKickstart(args[1], reset=False)
+ except KickstartError:
+ # Handle the include file being provided over the
+ # network in a %pre script. This case comes up in the
+ # early parsing in anaconda.
+ if self.missingIncludeIsFatal:
+ raise
+
+ self._includeDepth -= 1
+ continue
+
+ # Now on to the main event.
+ if self._state == STATE_COMMANDS:
+ if args[0] == "%ksappend":
+ # This is handled by the preprocess* functions, so continue.
+ continue
+ elif args[0][0] == '%':
+ # This is the beginning of a new section. Handle its header
+ # here.
+ newSection = args[0]
+ if not self._validState(newSection):
+ raise KickstartParseError, formatErrorMsg(lineno, msg=_("Unknown kickstart section: %s" % newSection))
+
+ self._state = newSection
+ obj = self._sections[self._state]
+ self._tryFunc(lambda: obj.handleHeader(lineno, args))
+
+ # This will handle all section processing, kicking us back
+ # out to STATE_COMMANDS at the end with the current line
+ # being the next section header, etc.
+ lineno = self._readSection(lineIter, lineno)
+ else:
+ # This is a command in the command section. Dispatch to it.
+ self._tryFunc(lambda: self.handleCommand(lineno, args))
+ elif self._state == STATE_END:
+ break
+
+ def readKickstartFromString (self, s, reset=True):
+ """Process a kickstart file, provided as the string str."""
+ if reset:
+ self._reset()
+
+ # Add a "" to the end of the list so the string reader acts like the
+ # file reader and we only get StopIteration when we're after the final
+ # line of input.
+ i = PutBackIterator(s.splitlines(True) + [""])
+ self._stateMachine (i)
+
+ def readKickstart(self, f, reset=True):
+ """Process a kickstart file, given by the filename f."""
+ if reset:
+ self._reset()
+
+ # an %include might not specify a full path. if we don't try to figure
+ # out what the path should have been, then we're unable to find it
+ # requiring full path specification, though, sucks. so let's make
+ # the reading "smart" by keeping track of what the path is at each
+ # include depth.
+ if not os.path.exists(f):
+ if self.currentdir.has_key(self._includeDepth - 1):
+ if os.path.exists(os.path.join(self.currentdir[self._includeDepth - 1], f)):
+ f = os.path.join(self.currentdir[self._includeDepth - 1], f)
+
+ cd = os.path.dirname(f)
+ if not cd.startswith("/"):
+ cd = os.path.abspath(cd)
+ self.currentdir[self._includeDepth] = cd
+
+ try:
+ s = urlread(f)
+ except grabber.URLGrabError, e:
+ raise KickstartError, formatErrorMsg(0, msg=_("Unable to open input kickstart file: %s") % e.strerror)
+
+ self.readKickstartFromString(s, reset=False)
+
+ def setupSections(self):
+ """Install the sections all kickstart files support. You may override
+ this method in a subclass, but should avoid doing so unless you know
+ what you're doing.
+ """
+ self._sections = {}
+
+ # Install the sections all kickstart files support.
+ self.registerSection(PreScriptSection(self.handler, dataObj=Script))
+ self.registerSection(PostScriptSection(self.handler, dataObj=Script))
+ self.registerSection(TracebackScriptSection(self.handler, dataObj=Script))
+ self.registerSection(PackageSection(self.handler))
diff --git a/scripts/lib/wic/3rdparty/pykickstart/sections.py b/scripts/lib/wic/3rdparty/pykickstart/sections.py
new file mode 100644
index 0000000000..44df856b8d
--- /dev/null
+++ b/scripts/lib/wic/3rdparty/pykickstart/sections.py
@@ -0,0 +1,244 @@
+#
+# sections.py: Kickstart file sections.
+#
+# Chris Lumens <clumens@redhat.com>
+#
+# Copyright 2011 Red Hat, Inc.
+#
+# This copyrighted material is made available to anyone wishing to use, modify,
+# copy, or redistribute it subject to the terms and conditions of the GNU
+# General Public License v.2. This program is distributed in the hope that it
+# will be useful, but WITHOUT ANY WARRANTY expressed or implied, including the
+# implied warranties of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# See the GNU General Public License for more details.
+#
+# 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., 51
+# Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. Any Red Hat
+# trademarks that are incorporated in the source code or documentation are not
+# subject to the GNU General Public License and may only be used or replicated
+# with the express permission of Red Hat, Inc.
+#
+"""
+This module exports the classes that define a section of a kickstart file. A
+section is a chunk of the file starting with a %tag and ending with a %end.
+Examples of sections include %packages, %pre, and %post.
+
+You may use this module to define your own custom sections which will be
+treated just the same as a predefined one by the kickstart parser. All that
+is necessary is to create a new subclass of Section and call
+parser.registerSection with an instance of your new class.
+"""
+from constants import *
+from options import KSOptionParser
+from version import *
+
+class Section(object):
+ """The base class for defining kickstart sections. You are free to
+ subclass this as appropriate.
+
+ Class attributes:
+
+ allLines -- Does this section require the parser to call handleLine
+ for every line in the section, even blanks and comments?
+ sectionOpen -- The string that denotes the start of this section. You
+ must start your tag with a percent sign.
+ timesSeen -- This attribute is for informational purposes only. It is
+ incremented every time handleHeader is called to keep
+ track of the number of times a section of this type is
+ seen.
+ """
+ allLines = False
+ sectionOpen = ""
+ timesSeen = 0
+
+ def __init__(self, handler, **kwargs):
+ """Create a new Script instance. At the least, you must pass in an
+ instance of a baseHandler subclass.
+
+ Valid kwargs:
+
+ dataObj --
+ """
+ self.handler = handler
+
+ self.version = self.handler.version
+
+ self.dataObj = kwargs.get("dataObj", None)
+
+ def finalize(self):
+ """This method is called when the %end tag for a section is seen. It
+ is not required to be provided.
+ """
+ pass
+
+ def handleLine(self, line):
+ """This method is called for every line of a section. Take whatever
+ action is appropriate. While this method is not required to be
+ provided, not providing it does not make a whole lot of sense.
+
+ Arguments:
+
+ line -- The complete line, with any trailing newline.
+ """
+ pass
+
+ def handleHeader(self, lineno, args):
+ """This method is called when the opening tag for a section is seen.
+ Not all sections will need this method, though all provided with
+ kickstart include one.
+
+ Arguments:
+
+ args -- A list of all strings passed as arguments to the section
+ opening tag.
+ """
+ self.timesSeen += 1
+
+class NullSection(Section):
+ """This defines a section that pykickstart will recognize but do nothing
+ with. If the parser runs across a %section that has no object registered,
+ it will raise an error. Sometimes, you may want to simply ignore those
+ sections instead. This class is useful for that purpose.
+ """
+ def __init__(self, *args, **kwargs):
+ """Create a new NullSection instance. You must pass a sectionOpen
+ parameter (including a leading '%') for the section you wish to
+ ignore.
+ """
+ Section.__init__(self, *args, **kwargs)
+ self.sectionOpen = kwargs.get("sectionOpen")
+
+class ScriptSection(Section):
+ allLines = True
+
+ def __init__(self, *args, **kwargs):
+ Section.__init__(self, *args, **kwargs)
+ self._script = {}
+ self._resetScript()
+
+ def _getParser(self):
+ op = KSOptionParser(self.version)
+ op.add_option("--erroronfail", dest="errorOnFail", action="store_true",
+ default=False)
+ op.add_option("--interpreter", dest="interpreter", default="/bin/sh")
+ op.add_option("--log", "--logfile", dest="log")
+ return op
+
+ def _resetScript(self):
+ self._script = {"interp": "/bin/sh", "log": None, "errorOnFail": False,
+ "lineno": None, "chroot": False, "body": []}
+
+ def handleLine(self, line):
+ self._script["body"].append(line)
+
+ def finalize(self):
+ if " ".join(self._script["body"]).strip() == "":
+ return
+
+ kwargs = {"interp": self._script["interp"],
+ "inChroot": self._script["chroot"],
+ "lineno": self._script["lineno"],
+ "logfile": self._script["log"],
+ "errorOnFail": self._script["errorOnFail"],
+ "type": self._script["type"]}
+
+ s = self.dataObj (self._script["body"], **kwargs)
+ self._resetScript()
+
+ if self.handler:
+ self.handler.scripts.append(s)
+
+ def handleHeader(self, lineno, args):
+ """Process the arguments to a %pre/%post/%traceback header for later
+ setting on a Script instance once the end of the script is found.
+ This method may be overridden in a subclass if necessary.
+ """
+ Section.handleHeader(self, lineno, args)
+ op = self._getParser()
+
+ (opts, extra) = op.parse_args(args=args[1:], lineno=lineno)
+
+ self._script["interp"] = opts.interpreter
+ self._script["lineno"] = lineno
+ self._script["log"] = opts.log
+ self._script["errorOnFail"] = opts.errorOnFail
+ if hasattr(opts, "nochroot"):
+ self._script["chroot"] = not opts.nochroot
+
+class PreScriptSection(ScriptSection):
+ sectionOpen = "%pre"
+
+ def _resetScript(self):
+ ScriptSection._resetScript(self)
+ self._script["type"] = KS_SCRIPT_PRE
+
+class PostScriptSection(ScriptSection):
+ sectionOpen = "%post"
+
+ def _getParser(self):
+ op = ScriptSection._getParser(self)
+ op.add_option("--nochroot", dest="nochroot", action="store_true",
+ default=False)
+ return op
+
+ def _resetScript(self):
+ ScriptSection._resetScript(self)
+ self._script["chroot"] = True
+ self._script["type"] = KS_SCRIPT_POST
+
+class TracebackScriptSection(ScriptSection):
+ sectionOpen = "%traceback"
+
+ def _resetScript(self):
+ ScriptSection._resetScript(self)
+ self._script["type"] = KS_SCRIPT_TRACEBACK
+
+class PackageSection(Section):
+ sectionOpen = "%packages"
+
+ def handleLine(self, line):
+ if not self.handler:
+ return
+
+ (h, s, t) = line.partition('#')
+ line = h.rstrip()
+
+ self.handler.packages.add([line])
+
+ def handleHeader(self, lineno, args):
+ """Process the arguments to the %packages header and set attributes
+ on the Version's Packages instance appropriate. This method may be
+ overridden in a subclass if necessary.
+ """
+ Section.handleHeader(self, lineno, args)
+ op = KSOptionParser(version=self.version)
+ op.add_option("--excludedocs", dest="excludedocs", action="store_true",
+ default=False)
+ op.add_option("--ignoremissing", dest="ignoremissing",
+ action="store_true", default=False)
+ op.add_option("--nobase", dest="nobase", action="store_true",
+ default=False)
+ op.add_option("--ignoredeps", dest="resolveDeps", action="store_false",
+ deprecated=FC4, removed=F9)
+ op.add_option("--resolvedeps", dest="resolveDeps", action="store_true",
+ deprecated=FC4, removed=F9)
+ op.add_option("--default", dest="defaultPackages", action="store_true",
+ default=False, introduced=F7)
+ op.add_option("--instLangs", dest="instLangs", type="string",
+ default="", introduced=F9)
+
+ (opts, extra) = op.parse_args(args=args[1:], lineno=lineno)
+
+ self.handler.packages.excludeDocs = opts.excludedocs
+ self.handler.packages.addBase = not opts.nobase
+ if opts.ignoremissing:
+ self.handler.packages.handleMissing = KS_MISSING_IGNORE
+ else:
+ self.handler.packages.handleMissing = KS_MISSING_PROMPT
+
+ if opts.defaultPackages:
+ self.handler.packages.default = True
+
+ if opts.instLangs:
+ self.handler.packages.instLangs = opts.instLangs
diff --git a/scripts/lib/wic/3rdparty/pykickstart/version.py b/scripts/lib/wic/3rdparty/pykickstart/version.py
new file mode 100644
index 0000000000..102cc37d80
--- /dev/null
+++ b/scripts/lib/wic/3rdparty/pykickstart/version.py
@@ -0,0 +1,197 @@
+#
+# Chris Lumens <clumens@redhat.com>
+#
+# Copyright 2006, 2007, 2008, 2009, 2010 Red Hat, Inc.
+#
+# This copyrighted material is made available to anyone wishing to use, modify,
+# copy, or redistribute it subject to the terms and conditions of the GNU
+# General Public License v.2. This program is distributed in the hope that it
+# will be useful, but WITHOUT ANY WARRANTY expressed or implied, including the
+# implied warranties of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# See the GNU General Public License for more details.
+#
+# 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., 51
+# Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. Any Red Hat
+# trademarks that are incorporated in the source code or documentation are not
+# subject to the GNU General Public License and may only be used or replicated
+# with the express permission of Red Hat, Inc.
+#
+"""
+Methods for working with kickstart versions.
+
+This module defines several symbolic constants that specify kickstart syntax
+versions. Each version corresponds roughly to one release of Red Hat Linux,
+Red Hat Enterprise Linux, or Fedora Core as these are where most syntax
+changes take place.
+
+This module also exports several functions:
+
+ makeVersion - Given a version number, return an instance of the
+ matching handler class.
+
+ returnClassForVersion - Given a version number, return the matching
+ handler class. This does not return an
+ instance of that class, however.
+
+ stringToVersion - Convert a string representation of a version number
+ into the symbolic constant.
+
+ versionToString - Perform the reverse mapping.
+
+ versionFromFile - Read a kickstart file and determine the version of
+ syntax it uses. This requires the kickstart file to
+ have a version= comment in it.
+"""
+import imputil, re, sys
+from urlgrabber import urlopen
+
+import gettext
+_ = lambda x: gettext.ldgettext("pykickstart", x)
+
+from pykickstart.errors import KickstartVersionError
+
+# Symbolic names for internal version numbers.
+RHEL3 = 900
+FC3 = 1000
+RHEL4 = 1100
+FC4 = 2000
+FC5 = 3000
+FC6 = 4000
+RHEL5 = 4100
+F7 = 5000
+F8 = 6000
+F9 = 7000
+F10 = 8000
+F11 = 9000
+F12 = 10000
+F13 = 11000
+RHEL6 = 11100
+F14 = 12000
+F15 = 13000
+F16 = 14000
+
+# This always points at the latest version and is the default.
+DEVEL = F16
+
+# A one-to-one mapping from string representations to version numbers.
+versionMap = {
+ "DEVEL": DEVEL,
+ "FC3": FC3, "FC4": FC4, "FC5": FC5, "FC6": FC6, "F7": F7, "F8": F8,
+ "F9": F9, "F10": F10, "F11": F11, "F12": F12, "F13": F13,
+ "F14": F14, "F15": F15, "F16": F16,
+ "RHEL3": RHEL3, "RHEL4": RHEL4, "RHEL5": RHEL5, "RHEL6": RHEL6
+}
+
+def stringToVersion(s):
+ """Convert string into one of the provided version constants. Raises
+ KickstartVersionError if string does not match anything.
+ """
+ # First try these short forms.
+ try:
+ return versionMap[s.upper()]
+ except KeyError:
+ pass
+
+ # Now try the Fedora versions.
+ m = re.match("^fedora.* (\d+)$", s, re.I)
+
+ if m and m.group(1):
+ if versionMap.has_key("FC" + m.group(1)):
+ return versionMap["FC" + m.group(1)]
+ elif versionMap.has_key("F" + m.group(1)):
+ return versionMap["F" + m.group(1)]
+ else:
+ raise KickstartVersionError(_("Unsupported version specified: %s") % s)
+
+ # Now try the RHEL versions.
+ m = re.match("^red hat enterprise linux.* (\d+)([\.\d]*)$", s, re.I)
+
+ if m and m.group(1):
+ if versionMap.has_key("RHEL" + m.group(1)):
+ return versionMap["RHEL" + m.group(1)]
+ else:
+ raise KickstartVersionError(_("Unsupported version specified: %s") % s)
+
+ # If nothing else worked, we're out of options.
+ raise KickstartVersionError(_("Unsupported version specified: %s") % s)
+
+def versionToString(version, skipDevel=False):
+ """Convert version into a string representation of the version number.
+ This is the reverse operation of stringToVersion. Raises
+ KickstartVersionError if version does not match anything.
+ """
+ if not skipDevel and version == versionMap["DEVEL"]:
+ return "DEVEL"
+
+ for (key, val) in versionMap.iteritems():
+ if key == "DEVEL":
+ continue
+ elif val == version:
+ return key
+
+ raise KickstartVersionError(_("Unsupported version specified: %s") % version)
+
+def versionFromFile(f):
+ """Given a file or URL, look for a line starting with #version= and
+ return the version number. If no version is found, return DEVEL.
+ """
+ v = DEVEL
+
+ fh = urlopen(f)
+
+ while True:
+ try:
+ l = fh.readline()
+ except StopIteration:
+ break
+
+ # At the end of the file?
+ if l == "":
+ break
+
+ if l.isspace() or l.strip() == "":
+ continue
+
+ if l[:9] == "#version=":
+ v = stringToVersion(l[9:].rstrip())
+ break
+
+ fh.close()
+ return v
+
+def returnClassForVersion(version=DEVEL):
+ """Return the class of the syntax handler for version. version can be
+ either a string or the matching constant. Raises KickstartValueError
+ if version does not match anything.
+ """
+ try:
+ version = int(version)
+ module = "%s" % versionToString(version, skipDevel=True)
+ except ValueError:
+ module = "%s" % version
+ version = stringToVersion(version)
+
+ module = module.lower()
+
+ try:
+ import pykickstart.handlers
+ sys.path.extend(pykickstart.handlers.__path__)
+ found = imputil.imp.find_module(module)
+ loaded = imputil.imp.load_module(module, found[0], found[1], found[2])
+
+ for (k, v) in loaded.__dict__.iteritems():
+ if k.lower().endswith("%shandler" % module):
+ return v
+ except:
+ raise KickstartVersionError(_("Unsupported version specified: %s") % version)
+
+def makeVersion(version=DEVEL):
+ """Return a new instance of the syntax handler for version. version can be
+ either a string or the matching constant. This function is useful for
+ standalone programs which just need to handle a specific version of
+ kickstart syntax (as provided by a command line argument, for example)
+ and need to instantiate the correct object.
+ """
+ cl = returnClassForVersion(version)
+ return cl()