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(r"^fedora.* (\d+)$", s, re.I) if m and m.group(1): if "FC" + m.group(1) in versionMap: return versionMap["FC" + m.group(1)] elif "F" + m.group(1) in versionMap: return versionMap["F" + m.group(1)] else: raise KickstartVersionError(_("Unsupported version specified: %s") % s) # Now try the RHEL versions. m = re.match(r"^red hat enterprise linux.* (\d+)([\.\d]*)$", s, re.I) if m and m.group(1): if "RHEL" + m.group(1) in versionMap: 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 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 = self._getParser() ns = op.parse_args(args=args[1:], lineno=lineno) if ns.defaultPackages and ns.nobase: raise KickstartParseError(formatErrorMsg(lineno, msg=_("--default and --nobase cannot be used together")), lineno=lineno) elif ns.defaultPackages and ns.nocore: raise KickstartParseError(formatErrorMsg(lineno, msg=_("--default and --nocore cannot be used together")), lineno=lineno) self.handler.packages.excludeDocs = ns.excludedocs self.handler.packages.addBase = not ns.nobase if ns.ignoremissing: self.handler.packages.handleMissing = KS_MISSING_IGNORE else: self.handler.packages.handleMissing = KS_MISSING_PROMPT if ns.defaultPackages: self.handler.packages.default = True if ns.instLangs is not None: self.handler.packages.instLangs = ns.instLangs self.handler.packages.nocore = ns.nocore self.handler.packages.multiLib = ns.multiLib self.handler.packages.excludeWeakdeps = ns.excludeWeakdeps self.handler.packages.timeout = ns.timeout self.handler.packages.retries = ns.retries self.handler.packages.seen = True
def parse(self, args): (ns, extra) = self.op.parse_known_args(args=args, lineno=self.lineno) if not ns.format: ns.preexist = True vg = self.handler.VolGroupData() self.set_to_obj(ns, vg) vg.lineno = self.lineno if len(extra) == 0: raise KickstartParseError(formatErrorMsg(self.lineno, msg=_("volgroup must be given a VG name"))) elif any(arg for arg in extra if arg.startswith("-")): mapping = {"command": "volgroup", "options": extra} raise KickstartParseError(formatErrorMsg(self.lineno, msg=_("Unexpected arguments to %(command)s command: %(options)s") % mapping)) if len(extra) == 1 and not ns.preexist: raise KickstartParseError(formatErrorMsg(self.lineno, msg=_("volgroup must be given a list of partitions"))) elif len(extra) > 1 and ns.preexist: raise KickstartParseError(formatErrorMsg(self.lineno, msg=_("Members may not be specified for preexisting volgroup"))) vg.vgname = extra[0] if len(extra) > 1: vg.physvols = extra[1:] # Check for duplicates in the data list. if vg in self.dataList(): warnings.warn(_("A volgroup with the name %s has already been defined.") % vg.vgname) return vg
def parse(self, args): ns = self.op.parse_args(args=args, lineno=self.lineno) snap_data = self.dataClass() # pylint: disable=not-callable self.set_to_obj(ns, snap_data) snap_data.lineno = self.lineno # Check for duplicates if snap_data.name in [snap.name for snap in self.dataList()]: msg = (_("Snapshot with the name %s has been already defined!") % snap_data.name) raise KickstartParseError(msg, lineno=self.lineno) if snap_data.when is None: msg = _("Snapshot \"when\" parameter must be specified!") raise KickstartParseError(msg, lineno=self.lineno) groups = snap_data.origin.split('/') if len(groups) != 2 or len(groups[0]) == 0 or len(groups[1]) == 0: msg = (_("Snapshot origin %s must be specified by VG/LV!") % snap_data.origin) raise KickstartParseError(msg, lineno=self.lineno) # Check if value in a '--when' param is valid if snap_data.when != "" and snap_data.when not in self.whenMap.values(): msg = (_("Snapshot when param must have one of these values %s!") % self.whenMap.keys()) raise KickstartParseError(msg, lineno=self.lineno) return snap_data
def main(argv=None): opts = parse_args(argv) if not opts.kscfg: return (1, _("Need to specify a config to flatten")) try: ksversion = makeVersion(opts.version) except KickstartVersionError: print(_("The version %s is not supported by pykickstart") % opts.version) sys.exit(1) ksparser = pykickstart.parser.KickstartParser(ksversion) try: ksparser.readKickstart(opts.kscfg) except IOError as msg: return (1, _("Failed to read kickstart file '%(filename)s' : %(error_msg)s") % {"filename": opts.kscfg, "error_msg": msg}) except pykickstart.errors.KickstartError as e: return (1, _("Failed to parse kickstart file '%(filename)s' : %(error_msg)s") % {"filename": opts.kscfg, "error_msg": e}) if opts.output: try: f = open(opts.output, 'w') except IOError as msg: return (1, _("Failed to open output file '%(filename)s' : %(error_msg)s") % {"filename": opts.output, "error_msg": msg}) else: f = sys.stdout f.write("%s" % ksparser.handler) if opts.output: f.close() return (0, '')
def check_values (self, values, args): def seen(option): return option in self.option_seen def usedTooNew(option): return option.introduced and option.introduced > self.version def usedDeprecated(option): return option.deprecated def usedRemoved(option): return option.removed and option.removed <= self.version for option in [o for o in self.option_list if isinstance(o, Option)]: if option.required and not seen(option): raise KickstartValueError(formatErrorMsg(self.lineno, _("Option %s is required") % option)) elif seen(option) and usedTooNew(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(option) and usedRemoved(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(option) and usedDeprecated(option) and self.version >= option.deprecated: 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(self, args): (ns, extra) = self.op.parse_known_args(args=args, lineno=self.lineno) if len(extra) > 1: raise KickstartParseError( formatErrorMsg(self.lineno, msg=_("Only one partition may be specified for driverdisk command.")) ) elif any(arg for arg in extra if arg.startswith("-")): mapping = {"command": "driverdisk", "options": extra} raise KickstartParseError( formatErrorMsg(self.lineno, msg=_("Unexpected arguments to %(command)s command: %(options)s") % mapping) ) if len(extra) == 1 and ns.source: raise KickstartParseError( formatErrorMsg( self.lineno, msg=_("Only one of --source and partition may be specified for driverdisk command.") ) ) if not extra and not ns.source: raise KickstartParseError( formatErrorMsg( self.lineno, msg=_("One of --source or partition must be specified for driverdisk command.") ) ) ddd = self.handler.DriverDiskData() self.set_to_obj(ns, ddd) ddd.lineno = self.lineno if len(extra) == 1: ddd.partition = extra[0] return ddd
def parse(self, args): # call the overridden command to do it's job first retval = F21_Network.parse(self, args) # validate the network interface name error_message = validate_network_interface_name(retval.interfacename) # something is wrong with the interface name if error_message: raise KickstartParseError(error_message, lineno=self.lineno) if retval.bridgeopts: if not retval.bridgeslaves: msg = _("Option --bridgeopts requires --bridgeslaves to be specified") raise KickstartParseError(msg, lineno=self.lineno) opts = retval.bridgeopts.split(",") for opt in opts: _key, _sep, value = opt.partition("=") if not value or "=" in value: msg = _("Bad format of --bridgeopts, expecting key=value options separated by ','") raise KickstartParseError(msg, lineno=self.lineno) if retval.bindto == BIND_TO_MAC: if retval.vlanid and not retval.bondopts: msg = _("--bindto=%s is not supported for this type of device") % BIND_TO_MAC raise KickstartParseError(msg, lineno=self.lineno) return retval
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
def parse(self, args): ns = self.op.parse_args(args=args, lineno=self.lineno) self.set_to_self(ns) # just "timezone" without any arguments and timezone specification doesn't really make sense, # so throw an error when we see it (it might even be an indication of an incorrect machine generated kickstart) if not args: error_message = _("At least one option and/or an argument are expected for the %s command") % "timezone" raise KickstartParseError(formatErrorMsg(self.lineno, msg=error_message)) # To be able to support the timezone command being used without # a timezone specification: # - we don't call the parse() method of the ancestors # -> due to the FC3 parse() method that would be eventually called, # which throws an exception if no timezone specification is provided # - we implement the relevant functionality of the ancestor methods here if len(ns.timezone) == 1: self.timezone = ns.timezone[0] elif len(ns.timezone) > 1: error_message = _("One or zero arguments are expected for the %s command") % "timezone" raise KickstartParseError(formatErrorMsg(self.lineno, msg=error_message)) if self.ntpservers and self.nontp: msg = formatErrorMsg(self.lineno, msg=_("Options --nontp and --ntpservers are mutually exclusive")) raise KickstartParseError(msg) return self
def parse(self, args): (opts, extra) = self.op.parse_args(args=args, lineno=self.lineno) data = self.handler.BTRFSData() self._setToObj(self.op, opts, data) data.lineno = self.lineno if len(extra) == 0: raise KickstartValueError(formatErrorMsg(self.lineno, msg=_("btrfs must be given a mountpoint"))) if len(extra) == 1 and not data.subvol: raise KickstartValueError(formatErrorMsg(self.lineno, msg=_("btrfs must be given a list of partitions"))) elif len(extra) == 1: raise KickstartValueError(formatErrorMsg(self.lineno, msg=_("btrfs subvol requires specification of parent volume"))) if data.subvol and not data.name: raise KickstartValueError(formatErrorMsg(self.lineno, msg=_("btrfs subvolume requires a name"))) data.mountpoint = extra[0] data.devices = extra[1:] # Check for duplicates in the data list. if data in self.dataList(): warnings.warn(_("A btrfs volume with the mountpoint %s has already been defined.") % data.label) return data
def _parseJoin(self, args): try: # We only support these args opts, remaining = getopt.getopt(args, "", ("client-software=", "server-software=", "membership-software=", "one-time-password="******"no-password", "computer-ou=")) except getopt.GetoptError as ex: raise KickstartParseError(formatErrorMsg(self.lineno, msg=_( "Invalid realm arguments: %s") % ex)) if len(remaining) != 1: raise KickstartParseError(formatErrorMsg(self.lineno, msg=_( "Specify only one realm to join"))) # Parse successful, just use this as the join command self.join_realm = remaining[0] self.join_args = args # Build a discovery command self.discover_options = [] supported_discover_options = ("--client-software", "--server-software", "--membership-software") for (o, a) in opts: if o in supported_discover_options: self.discover_options.append("%s=%s" % (o, a))
def parse(self, args): (opts, extra) = self.op.parse_args(args=args, lineno=self.lineno) vg = self.handler.VolGroupData() self._setToObj(self.op, opts, vg) vg.lineno = self.lineno if len(extra) == 0: raise KickstartParseError(formatErrorMsg(self.lineno, msg=_("volgroup must be given a VG name"))) if len(extra) == 1 and not opts.preexist: raise KickstartValueError(formatErrorMsg(self.lineno, msg=_("volgroup must be given a list of partitions"))) elif len(extra) > 1 and opts.preexist: raise KickstartValueError( formatErrorMsg(self.lineno, msg=_("Members may not be specified for preexisting volgroup")) ) vg.vgname = extra[0] if len(extra) > 1: vg.physvols = extra[1:] # Check for duplicates in the data list. if vg in self.dataList(): warnings.warn(_("A volgroup with the name %s has already been defined.") % vg.vgname) return vg
def main(): opts = parse_args() if not opts.kscfg: print(_("Need to specify a config to flatten"), file=sys.stderr) sys.exit(1) ksversion = makeVersion(opts.version) ksparser = pykickstart.parser.KickstartParser(ksversion) try: ksparser.readKickstart(opts.kscfg) except IOError as msg: print(_("Failed to read kickstart file '%(filename)s' : %(error_msg)s") % {"filename": opts.kscfg, "error_msg": msg}, file=sys.stderr) sys.exit(1) except pykickstart.errors.KickstartError as e: print(_("Failed to parse kickstart file '%(filename)s' : %(error_msg)s") % {"filename": opts.kscfg, "error_msg": e}, file=sys.stderr) sys.exit(1) if opts.output: try: f = open(opts.output, 'w') except IOError as msg: print(_("Failed to open output file '%(filename)s' : %(error_msg)s") % {"filename": opts.output, "error_msg": msg}, file=sys.stderr) sys.exit(1) else: f = sys.stdout f.write("%s" % ksparser.handler) f.close()
def _parse_optional(self, arg_string): def usedTooNew(action): return action.introduced and action.introduced > self.version def usedRemoved(action): return action.removed and action.removed <= self.version option_tuple = ArgumentParser._parse_optional(self, arg_string) if option_tuple is None or option_tuple[0] is None: return option_tuple action = option_tuple[0] if usedTooNew(action): mapping = {"option": action.option_strings[0], "intro": versionToString(action.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 usedRemoved(action): mapping = {"option": action.option_strings[0], "removed": versionToString(action.removed), "version": versionToString(self.version)} if action.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 action.deprecated == True or (self.version and self.version >= action.deprecated): mapping = {"lineno": self.lineno, "option": action.option_strings[0]} 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 option_tuple
def parse(self, args): # the 'mount' command can't be used together with any other # partitioning-related command conflicting_command = None # seen indicates that the corresponding # command has been seen in kickstart if self.handler.autopart.seen: conflicting_command = "autopart" if self.handler.partition.seen: conflicting_command = "part/partition" elif self.handler.raid.seen: conflicting_command = "raid" elif self.handler.volgroup.seen: conflicting_command = "volgroup" elif self.handler.logvol.seen: conflicting_command = "logvol" elif hasattr(self.handler, "reqpart") and self.handler.reqpart.seen: conflicting_command = "reqpart" if conflicting_command: # allow for translation of the error message errorMsg = _("The '%s' and 'mount' commands can't be used at the same time") % \ conflicting_command raise KickstartParseError(errorMsg, lineno=self.lineno) (ns, extra) = self.op.parse_known_args(args=args, lineno=self.lineno) if extra: mapping = {"command": "mount", "options": extra} raise KickstartParseError(_("Unexpected arguments to %(command)s command: %(options)s") % mapping, lineno=self.lineno) md = self.dataClass() # pylint: disable=not-callable self.set_to_obj(ns, md) md.lineno = self.lineno md.device = ns.device[0] md.mount_point = ns.mntpoint[0] if md.mount_point.lower() != "none" and not md.mount_point.startswith("/"): raise KickstartParseError(_("Invalid mount point '%s' given") % md.mount_point, lineno=self.lineno) if md.reformat is False and md.mkfs_opts: raise KickstartParseError(_("'--mkfsoptions' requires --reformat"), lineno=self.lineno) # The semantics is as follows: # --reformat -> just reformat with the same format as existing # --reformat=SOME_FMT -> reformat to given format # no '--reformat' -> don't reformat # # md.reformat can either be 'False' (not specified), 'True' (just # '--reformat') or a non-empty string ('--reformat=FORMAT'). Only the # last case requires special treatment. if md.reformat and md.reformat is not True: # a new format given md.format = md.reformat md.reformat = True return md
def _format_error_message(lineno, msg=""): """Properly format the error message msg in an exception. This function should be called only in exceptions to format the error messages. """ if msg: return _("The following problem occurred on line %(lineno)s of the kickstart file:" "\n\n%(msg)s\n") % {"lineno": lineno, "msg": msg} return _("There was a problem reading from line %s of the kickstart file") % lineno
def parse(self, args): retval = F14_Url.parse(self, args) if self.url and self.mirrorlist: raise KickstartParseError(formatErrorMsg(self.lineno, msg=_("Only one of --url and --mirrorlist may be specified for url command."))) if not self.url and not self.mirrorlist: raise KickstartParseError(formatErrorMsg(self.lineno, msg=_("One of --url or --mirrorlist must be specified for url command."))) return retval
def parse(self, args): retval = F21_LogVol.parse(self, args) if not retval.format and retval.mkfsopts: raise KickstartValueError(formatErrorMsg(self.lineno, msg=_("--mkfsoptions with --noformat has no effect."))) if retval.fsprofile and retval.mkfsopts: raise KickstartValueError(formatErrorMsg(self.lineno, msg=_("--mkfsoptions and --fsprofile cannot be used together."))) return retval
def parse(self, args): retval = F14_Partition.parse(self, args) if retval.resize and not retval.onPart: raise KickstartParseError(formatErrorMsg(self.lineno, msg=_("--resize can only be used in conjunction with --onpart"))) if retval.resize and not retval.size: raise KickstartParseError(formatErrorMsg(self.lineno, msg=_("--resize requires --size to specify new size"))) return retval
def ksboolean(value): try: if value.lower() in ("on", "yes", "true", "1"): return True elif value.lower() in ("off", "no", "false", "0"): return False else: raise ArgumentTypeError(_("invalid boolean value: %r") % value) except AttributeError: raise ArgumentTypeError(_("invalid boolean value: %r") % value)
def parse_args(): parser = argparse.ArgumentParser() parser.add_argument("-c", "--config", dest="kscfg", required=True, help=_("Path to kickstart config file")) parser.add_argument("-v", "--version", dest="version", default=DEVEL, help=_("Kickstart version to use for interpreting config")) parser.add_argument("-o", "--output", dest="output", help=_("Write flattened config to OUTPUT")) return parser.parse_args()
def parse(self, args): retval = F15_LogVol.parse(self, args) if retval.resize and not retval.preexist: raise KickstartParseError(formatErrorMsg(self.lineno, msg=_("--resize can only be used in conjunction with --useexisting"))) if retval.resize and not retval.size: raise KickstartParseError(formatErrorMsg(self.lineno, msg=_("--resize requires --size to indicate new size"))) return retval
def parse(self, args): (opts, extra) = self.op.parse_args(args=args, lineno=self.lineno) self._setToSelf(self.op, opts) if len(extra) != 0: raise KickstartValueError(formatErrorMsg(self.lineno, msg=_("Kickstart command %s does not take any arguments") % "eula")) if not self.agreed: raise KickstartValueError(formatErrorMsg(self.lineno, msg=_("Kickstart command eula expects the --agreed option"))) return self
def parse(self, args): (_ns, extra) = self.op.parse_known_args(args=args, lineno=self.lineno) if len(extra) != 1: raise KickstartParseError(formatErrorMsg(self.lineno, msg=_("Kickstart command %s requires one argument") % "iscsiname")) elif any(arg for arg in extra if arg.startswith("-")): mapping = {"command": "iscsiname", "options": extra} raise KickstartParseError(formatErrorMsg(self.lineno, msg=_("Unexpected arguments to %(command)s command: %(options)s") % mapping)) self.iscsiname = extra[0] return self
def _load_url(location): '''Load a location (URL or filename) and return contents as string''' try: request = requests.get(location, verify=SSL_VERIFY) except SSLError as e: raise KickstartError(_('Error securely accessing URL "%s"') % location + ': {e}'.format(e=str(e))) except RequestException as e: raise KickstartError(_('Error accessing URL "%s"') % location + ': {e}'.format(e=str(e))) return request.content
def parse(self, args): (_ns, extra) = self.op.parse_known_args(args=args, lineno=self.lineno) if len(_ns.kbd) != 1: raise KickstartParseError(formatErrorMsg(self.lineno, msg=_("Kickstart command %s requires one argument") % "keyboard")) elif extra: mapping = {"command": "keyboard", "options": extra} raise KickstartParseError(formatErrorMsg(self.lineno, msg=_("Unexpected arguments to %(command)s command: %(options)s") % mapping)) self.keyboard = _ns.kbd[0] return self
def _parseArguments(self, string): if self.join_realm: raise KickstartParseError(_("The realm command 'join' should only be specified once"), lineno=self.lineno) args = shlex.split(string) if not args: raise KickstartParseError(_("Missing realm command arguments"), lineno=self.lineno) command = args.pop(0) if command == "join": self._parseJoin(args) else: raise KickstartParseError(_("Unsupported realm '%s' command") % command, lineno=self.lineno)
def parse(self, args): (ns, extra) = self.op.parse_known_args(args=args, lineno=self.lineno) if not ns.password: raise KickstartParseError(_("A single argument is expected for the %s command") % "rootpw", lineno=self.lineno) elif extra: mapping = {"command": "rootpw", "options": extra} raise KickstartParseError(_("Unexpected arguments to %(command)s command: %(options)s") % mapping, lineno=self.lineno) self.set_to_self(ns) return self
def parse(self, args): (ns, extra) = self.op.parse_known_args(args=args, lineno=self.lineno) self.set_to_self(ns) if extra: raise KickstartParseError(_("Kickstart command %s does not take any arguments") % "eula", lineno=self.lineno) if not self.agreed: raise KickstartParseError(_("Kickstart command eula expects the --agreed option"), lineno=self.lineno) return self
def _when_cb(self, value): if value.lower() in self.whenMap: return self.whenMap[value.lower()] else: msg = _("Invalid snapshot when parameter: %s") % value raise KickstartParseError(formatErrorMsg(self.lineno, msg=msg), lineno=self.lineno)
def parse(self, args): (opts, extra) = self.op.parse_args(args=args, lineno=self.lineno) if len(extra) == 0: raise KickstartValueError(formatErrorMsg(self.lineno, msg=_("Mount point required for %s") % "logvol")) lvd = self.handler.LogVolData() self._setToObj(self.op, opts, lvd) lvd.lineno = self.lineno lvd.mountpoint=extra[0] # Check for duplicates in the data list. if lvd in self.dataList(): warnings.warn(_("A logical volume with the name %s has already been defined in volume group %s.") % (lvd.name, lvd.vgname)) return lvd
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 cmd not in self.commands: raise KickstartParseError(_("Unknown command: %s") % cmd, lineno=lineno) elif self.commands[cmd] is not None: self.commands[cmd].currentCmd = cmd self.commands[cmd].currentLine = self.currentLine self.commands[cmd].lineno = lineno self.commands[cmd].seen = True # The parser returns the data object that was modified. This is either # the command handler object itself (a KickstartCommand object), or it's # a BaseData subclass instance that should be put into the command's # dataList. The latter is done via side effects. # # Regardless, return the object that was given to us by the parser. obj = self.commands[cmd].parse(args[1:]) # Here's the side effect part - don't worry about lst not being returned. lst = self.commands[cmd].dataList() if isinstance(obj, BaseData) and lst is not None: lst.append(obj) return obj
def parse(self, args): retval = F15_Bootloader.parse(self, args) if "," in retval.bootDrive: # pylint: disable=no-member raise KickstartParseError(formatErrorMsg(self.lineno, msg=_("--boot-drive accepts only one argument"))) return retval
def _processGroup(self, line): op = KSOptionParser(prog="", description="", version=version.DEVEL) op.add_argument("--nodefaults", action="store_true", default=False, help="", version=version.DEVEL) op.add_argument("--optional", action="store_true", default=False, help="", version=version.DEVEL) (ns, extra) = op.parse_known_args(args=line.split()) if ns.nodefaults and ns.optional: raise KickstartParseError(_("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 grp in [g.name for g in self.groupList]: return if ns.nodefaults: self.groupList.append(Group(name=grp, include=constants.GROUP_REQUIRED)) elif ns.optional: self.groupList.append(Group(name=grp, include=constants.GROUP_ALL)) else: self.groupList.append(Group(name=grp, include=constants.GROUP_DEFAULT))
def returnClassForVersion(version=DEVEL): """Return the class of the syntax handler for version. version can be either a string or the matching constant. Raises KickstartVersionError 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: _path = os.path.join(os.path.dirname(__file__), "handlers/") sys.path.extend([_path]) loaded = importlib.import_module(module) for (k, v) in list(loaded.__dict__.items()): if k.lower().endswith("%shandler" % module): return v except: raise KickstartVersionError( _("Unsupported version specified: %s") % version)
def methodToRepo(self): if not self.handler.method.url: raise KickstartError(formatErrorMsg(self.handler.method.lineno, msg=_("Method must be a url to be added to the repo list."))) reponame = "ks-method-url" repourl = self.handler.method.url rd = self.handler.RepoData(name=reponame, baseurl=repourl) return rd
def _type_cb(self, value): if value.lower() in self.typeMap: return self.typeMap[value.lower()] else: raise KickstartParseError( formatErrorMsg(self.lineno, msg=_("Invalid autopart type: %s") % value))
def parse(self, args): # call the overriden command to do its job first retval = F18_AutoPart.parse(self, args) # Using autopart together with other partitioning command such as # part/partition, raid, logvol or volgroup can lead to hard to debug # behavior that might among other result into an unbootable system. # # Therefore if any of those commands is detected in the same kickstart # together with autopart, an error is raised and installation is # aborted. conflicting_command = "" # seen indicates that the corresponding # command has been seen in kickstart if self.handler.partition.seen: conflicting_command = "part/partition" elif self.handler.raid.seen: conflicting_command = "raid" elif self.handler.volgroup.seen: conflicting_command = "volgroup" elif self.handler.logvol.seen: conflicting_command = "logvol" if conflicting_command: # allow for translation of the error message errorMsg = _( "The %s and autopart commands can't be used at the same time" ) % conflicting_command raise KickstartParseError(formatErrorMsg(self.lineno, msg=errorMsg)) return retval
def parse(self, args): # call the overridden command to do it's job first retval = F21_Network.parse(self, args) if retval.bridgeopts: if not retval.bridgeslaves: msg = _("Option --bridgeopts requires --bridgeslaves to be specified") raise KickstartParseError(msg, lineno=self.lineno) opts = retval.bridgeopts.split(",") for opt in opts: _key, _sep, value = opt.partition("=") if not value or "=" in value: msg = _("Bad format of --bridgeopts, expecting key=value options separated by ','") raise KickstartParseError(msg, lineno=self.lineno) return retval
def parse(self, args): ns = self.op.parse_args(args=args, lineno=self.lineno) dd = FC6_MpPathData() self.set_to_obj(ns, dd) dd.lineno = self.lineno dd.mpdev = dd.name.split('/')[-1] parent = None for x in range(0, len(self.mpaths)): mpath = self.mpaths[x] for path in mpath.paths: if path.device == dd.device: mapping = { "device": path.device, "multipathdev": path.mpdev } raise KickstartParseError( formatErrorMsg( self.lineno, msg= _("Device '%(device)s' is already used in multipath '%(multipathdev)s'" ) % mapping)) if mpath.name == dd.mpdev: parent = x if parent is None: mpath = self.dataClass(name=dd.name) # pylint: disable=not-callable mpath.paths.append(dd) return mpath else: mpath = self.mpaths[parent] mpath.paths.append(dd) return dd
def load_to_file(location, destination): '''Load a destination URL or file into a file name. Type of input is inferred automatically. Arguments: location -- URL or file name to load destination -- destination file name to write to Returns: file name with contents Raises: KickstartError on error reading or writing''' if _is_url(location): contents = _load_url(location) # Write to file try: with open(destination, 'w') as fh: fh.write(contents) except IOError as e: raise KickstartError( _('Error writing file "%s":') % location + ': {e}'.format(e=str(e))) return destination else: _copy_file(location, destination) return destination
def _parseArguments(self, string): if self.join_realm: raise KickstartParseError( _("The realm command 'join' should only be specified once"), lineno=self.lineno) args = shlex.split(string) if not args: raise KickstartParseError(_("Missing realm command arguments"), lineno=self.lineno) command = args.pop(0) if command == "join": self._parseJoin(args) else: raise KickstartParseError(_("Unsupported realm '%s' command") % command, lineno=self.lineno)
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._includeDepth - 1 in self.currentdir: 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 = load_to_str(f) except KickstartError as e: raise KickstartError(_("Unable to open input kickstart file: %s") % str(e), lineno=0) self.readKickstartFromString(s, reset=False)
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 = imp.find_module(module) loaded = imp.load_module(module, found[0], found[1], found[2]) for (k, v) in list(loaded.__dict__.items()): if k.lower().endswith("%shandler" % module): return v except: found = None raise KickstartVersionError( _("Unsupported version specified: %s") % version) finally: # Closing opened files in imp.load_module if found and len(found) > 0: found[0].close()
def _copy_file(filename, destination): '''Copy file to destination''' try: shutil.copyfile(filename, destination) except OSError as e: raise KickstartError(_('Error copying file: %s') % str(e))
def parse(self, args): # first call the overriden method retval = F19_Raid.parse(self, args) # the raid command can't be used together with the autopart command # due to the hard to debug behavior their combination introduces if self.handler.autopart.seen: errorMsg = _( "The raid and autopart commands can't be used at the same time" ) raise KickstartParseError(errorMsg, lineno=self.lineno) # the same applies to the 'mount' command if hasattr(self.handler, "mount") and self.handler.mount.seen: errorMsg = _( "The raid and mount commands can't be used at the same time") raise KickstartParseError(errorMsg, lineno=self.lineno) return retval
def parse(self, args): (_ns, extra) = self.op.parse_known_args(args=args, lineno=self.lineno) if len(_ns.kbd) != 1: raise KickstartParseError( _("Kickstart command %s requires one argument") % "keyboard", lineno=self.lineno) elif extra: mapping = {"command": "keyboard", "options": extra} raise KickstartParseError( _("Unexpected arguments to %(command)s command: %(options)s") % mapping, lineno=self.lineno) self.keyboard = _ns.kbd[0] return self
def parse(self, args): (ns, extra) = self.op.parse_known_args(args=args, lineno=self.lineno) # because positional arguments with variable number of values # don't parse very well if not ns.partitions: if extra: ns.partitions = extra extra = [] elif len(ns.name) > 1: ns.partitions = ns.name[1:] ns.name = [ns.name[0]] if not ns.format: ns.preexist = True vg = self.dataClass() # pylint: disable=not-callable self.set_to_obj(ns, vg) vg.lineno = self.lineno if not ns.name: raise KickstartParseError(formatErrorMsg( self.lineno, msg=_("volgroup must be given a VG name")), lineno=self.lineno) if not any([ns.partitions, ns.preexist]): raise KickstartParseError(formatErrorMsg( self.lineno, msg=_("volgroup must be given a list of partitions")), lineno=self.lineno) elif ns.partitions and ns.preexist: raise KickstartParseError(formatErrorMsg( self.lineno, msg=_( "Members may not be specified for preexisting volgroup")), lineno=self.lineno) vg.vgname = ns.name[0] if ns.partitions: vg.physvols = ns.partitions # Check for duplicates in the data list. if vg in self.dataList(): warnings.warn( _("A volgroup with the name %s has already been defined.") % vg.vgname) return vg
def parse(self, args): (opts, _extra) = self.op.parse_args(args=args, lineno=self.lineno) self._setToSelf(self.op, opts) if len(self.disabled) == 0 and len(self.enabled) == 0: raise KickstartParseError(formatErrorMsg(self.lineno, msg=_("One of --disabled or --enabled must be provided."))) return self
def parse(self, args): if args: msg = _("Kickstart command %s does not take any arguments" ) % self.currentCmd raise KickstartParseError(formatErrorMsg(self.lineno, msg=msg), lineno=self.lineno) return self
def main(): opts = parse_args() if not opts.kscfg: print(_("Need to specify a config to flatten"), file=sys.stderr) sys.exit(1) ksversion = makeVersion(opts.version) ksparser = pykickstart.parser.KickstartParser(ksversion) try: ksparser.readKickstart(opts.kscfg) except IOError as msg: print( _("Failed to read kickstart file '%(filename)s' : %(error_msg)s") % { "filename": opts.kscfg, "error_msg": msg }, file=sys.stderr) sys.exit(1) except pykickstart.errors.KickstartError as e: print( _("Failed to parse kickstart file '%(filename)s' : %(error_msg)s") % { "filename": opts.kscfg, "error_msg": e }, file=sys.stderr) sys.exit(1) if opts.output: try: f = open(opts.output, 'w') except IOError as msg: print( _("Failed to open output file '%(filename)s' : %(error_msg)s") % { "filename": opts.output, "error_msg": msg }, file=sys.stderr) sys.exit(1) else: f = sys.stdout f.write("%s" % ksparser.handler) f.close()
def parse(self, args): ud = self.dataClass() # pylint: disable=not-callable (ns, extra) = self.op.parse_known_args(args=args, lineno=self.lineno) assert len(ns.sshkey) == 1 if extra: mapping = {"command": "sshkey", "options": extra} raise KickstartParseError(formatErrorMsg(self.lineno, msg=_("Unexpected arguments to %(command)s command: %(options)s") % mapping), lineno=self.lineno) self.set_to_obj(ns, ud) ud.key = ns.sshkey[0] ud.lineno = self.lineno if ud in self.dataList(): warnings.warn(_("An ssh user with the name %s has already been defined.") % ud.username) return ud
def parse(self, args): (_opts, extra) = self.op.parse_args(args=args, lineno=self.lineno) if len(extra) > 0: raise KickstartParseError(formatErrorMsg(self.lineno, msg=_("Kickstart command %s does not take any arguments") % self.currentCmd)) self.unsupported_hardware = True return self
def parse(self, args): # call the overriden command to do its job first retval = F20_AutoPart.parse(self, args) # btrfs is not a valid filesystem type if self.fstype == "btrfs": raise KickstartParseError(_( "autopart --fstype=btrfs is not valid fstype, use --type=btrfs instead" ), lineno=self.lineno) if self._typeAsStr() == "btrfs" and self.fstype: raise KickstartParseError( _("autopart --fstype cannot be used with --type=btrfs"), lineno=self.lineno) return retval
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 parse(self, args): (ns, extra) = self.op.parse_known_args(args=args, lineno=self.lineno) if len(extra) != 1: raise KickstartParseError( _("Kickstart command %s requires one argument") % "mouse", lineno=self.lineno) elif any(arg for arg in extra if arg.startswith("-")): mapping = {"command": "mouse", "options": extra} raise KickstartParseError( _("Unexpected arguments to %(command)s command: %(options)s") % mapping, lineno=self.lineno) self.set_to_self(ns) self.mouse = extra[0] return self
def _preprocessStateMachine (lineIter): l = None lineno = 0 retval = "" if six.PY3: retval = retval.encode(sys.getdefaultencoding()) while True: try: l = next(lineIter) except StopIteration: break # At the end of the file? if l == "": break lineno += 1 ksurl = None ll = l.strip() if not ll.startswith("%ksappend"): if six.PY3: l = l.encode(sys.getdefaultencoding()) retval += 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: contents = load_to_str(ksurl) except KickstartError as e: raise KickstartError(formatErrorMsg(lineno, msg=_("Unable to open %%ksappend file: %s") % str(e))) # If that worked, write the remote file to the output kickstart # file in one burst. This allows multiple %ksappend lines to # exist. if contents is not None: retval += contents.encode(sys.getdefaultencoding()) return retval
def parse(self, args): retval = F20_Raid.parse(self, args) if not retval.format and retval.mkfsopts: raise KickstartParseError(formatErrorMsg( self.lineno, msg=_("--mkfsoptions with --noformat has no effect.")), lineno=self.lineno) if retval.fsprofile and retval.mkfsopts: raise KickstartParseError(formatErrorMsg( self.lineno, msg=_( "--mkfsoptions and --fsprofile cannot be used together.")), lineno=self.lineno) return retval
def parse(self, args): FC6_Timezone.parse(self, args) if self.ntpservers and self.nontp: msg = _("Options --nontp and --ntpservers are mutually exclusive") raise KickstartParseError(msg, lineno=self.lineno) return self