summaryrefslogtreecommitdiffstats
path: root/pyanaconda/anaconda_optparse.py
diff options
context:
space:
mode:
Diffstat (limited to 'pyanaconda/anaconda_optparse.py')
-rw-r--r--pyanaconda/anaconda_optparse.py126
1 files changed, 126 insertions, 0 deletions
diff --git a/pyanaconda/anaconda_optparse.py b/pyanaconda/anaconda_optparse.py
new file mode 100644
index 000000000..ccb0361d7
--- /dev/null
+++ b/pyanaconda/anaconda_optparse.py
@@ -0,0 +1,126 @@
+#
+# anaconda_optparse.py: option parsing for anaconda (CLI and boot args)
+#
+# Copyright (C) 2012 Red Hat, Inc. All rights reserved.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty 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, see <http://www.gnu.org/licenses/>.
+#
+# Authors:
+# Will Woods <wwoods@redhat.com>
+
+from flags import BootArgs
+from optparse import OptionParser, OptionConflictError
+
+class AnacondaOptionParser(OptionParser):
+ """
+ Subclass of OptionParser that also examines boot arguments.
+
+ If the "bootarg_prefix" keyword argument is set, it's assumed that all
+ bootargs will start with that prefix.
+
+ "require_prefix" is a bool:
+ False: accept the argument with or without the prefix.
+ True: ignore the argument without the prefix. (default)
+ """
+ def __init__(self, *args, **kwargs):
+ self._boot_arg = dict()
+ self.bootarg_prefix = kwargs.pop("bootarg_prefix","")
+ self.require_prefix = kwargs.pop("require_prefix",True)
+ OptionParser.__init__(self, *args, **kwargs)
+
+ def add_option(self, *args, **kwargs):
+ """
+ Add a new option - like OptionParser.add_option.
+
+ The long options will be added to the list of boot args, unless
+ the keyword argument 'bootarg' is set to False.
+
+ Positional arguments that don't start with '-' are considered extra
+ boot args to look for.
+
+ NOTE: conflict_handler is currently ignored for boot args - they will
+ always raise OptionConflictError if they conflict.
+ """
+ # TODO: add kwargs to make an option commandline-only or boot-arg-only
+ flags = [a for a in args if a.startswith('-')]
+ bootargs = [a for a in args if not a.startswith('-')]
+ do_bootarg = kwargs.pop("bootarg", True)
+ option = OptionParser.add_option(self, *flags, **kwargs)
+ bootargs += [flag[2:] for flag in option._long_opts]
+ if do_bootarg:
+ for b in bootargs:
+ if b in self._boot_arg:
+ raise OptionConflictError(
+ "conflicting bootopt string: %s" % b, option)
+ else:
+ self._boot_arg[b] = option
+ return option
+
+ def _get_bootarg_option(self, arg):
+ """Find the correct Option for a given bootarg (if one exists)"""
+ if self.bootarg_prefix and arg.startswith(self.bootarg_prefix):
+ prefixed_option = True
+ arg = arg[len(self.bootarg_prefix):]
+ else:
+ prefixed_option = False
+ option = self._boot_arg.get(arg)
+
+ if self.require_prefix and not prefixed_option:
+ return None
+ if option and self.bootarg_prefix and not prefixed_option:
+ self.deprecated_bootargs.append(arg)
+ return option
+
+ def parse_boot_cmdline(self, cmdline, values=None):
+ """
+ Parse the boot cmdline and set appropriate values according to
+ the options set by add_option.
+
+ cmdline can be given as a string (to be parsed by BootArgs), or a
+ dict (or any object with .iteritems()) of {bootarg:value} pairs.
+
+ If cmdline is None, the cmdline data will be whatever BootArgs reads
+ by default (/proc/cmdline, /run/initramfs/etc/cmdline, /etc/cmdline).
+
+ If an option requires a value but the boot arg doesn't provide one,
+ we'll quietly not set anything.
+ """
+ if cmdline is None or type(cmdline) is str:
+ bootargs = BootArgs(cmdline)
+ else:
+ bootargs = cmdline
+ self.deprecated_bootargs = []
+ for arg, val in bootargs.iteritems():
+ option = self._get_bootarg_option(arg)
+ if option is None:
+ continue
+ if option.takes_value() and val is None:
+ continue # TODO: emit a warning or something there?
+ if option.action == "store_true" and val in ("0", "no", "off"):
+ # special case: "mpath=0" would otherwise set mpath to True
+ setattr(values, option.dest, False)
+ continue
+ option.process(arg, val, values, self)
+ return values
+
+ def parse_args(self, args=None, values=None, cmdline=None):
+ """
+ Like OptionParser.parse_args(), but also parses the boot cmdline.
+ (see parse_boot_cmdline for details on that process.)
+ Commandline arguments will override boot arguments.
+ """
+ if values is None:
+ values = self.get_default_values()
+ v = self.parse_boot_cmdline(cmdline, values)
+ return OptionParser.parse_args(self, args, v)