anaconda/anaconda-40.22.3.13/pyanaconda/core/kernel.py
2024-11-14 21:39:56 -08:00

186 lines
5.9 KiB
Python

#
# Copyright (C) 2018 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, or (at your option) any later version.
# 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 shlex
import glob
from collections import OrderedDict
from pyanaconda.core.constants import CMDLINE_APPEND, CMDLINE_LIST, CMDLINE_FILES
__all__ = ['KernelArguments', 'kernel_arguments']
# options might have the inst. prefix (used to differentiate
# boot options for the installer from other boot options)
BOOT_ARG_PREFIX = "inst."
class KernelArguments():
"""The kernel arguments.
Hold boot arguments as an OrderedDict.
"""
def __init__(self):
self._data = OrderedDict()
self._args_with_prefix = set()
@classmethod
def from_defaults(cls):
"""Load the default files.
:return: an instance of KernelArguments
"""
args = cls()
args.read(CMDLINE_FILES)
return args
@classmethod
def from_string(cls, cmdline):
"""Load the given cmdline.
:param cmdline: a string with the kernel cmdline
:return: an instance of KernelArguments
"""
args = cls()
args.read_string(cmdline)
return args
def read(self, filenames):
"""Read and parse a file name (or a list of file names).
Files that can't be read are silently ignored. The names
can contain \\*, ?, and character ranges expressed with [].
:param filenames: a file name or a list of file names
:return: a list of successfully read files
"""
readfiles = []
if isinstance(filenames, str):
filenames = [filenames]
# Expand any filename globs
filenames = [f for g in filenames for f in glob.glob(g)]
for f in filenames:
try:
self.read_string(open(f).read())
readfiles.append(f)
except OSError:
continue
return readfiles
def read_string(self, cmdline):
"""Read and parse a string.
:param cmdline: a string with the kernel command line
"""
cmdline = cmdline.strip()
# if the BOOT_IMAGE contains a space, pxelinux will strip one of the
# quotes leaving one at the end that shlex doesn't know what to do
# with
(left, middle, right) = cmdline.rpartition("BOOT_IMAGE=")
if right.count('"') % 2:
cmdline = left + middle + '"' + right
# shlex doesn't properly handle \\ (it removes them)
# which scrambles the spaces used in labels so use underscores
cmdline = cmdline.replace("\\x20", "_")
lst = shlex.split(cmdline)
for i in lst:
prefix_used = False
# drop the inst. prefix (if found)
if i.startswith(BOOT_ARG_PREFIX):
i = i[len(BOOT_ARG_PREFIX):]
prefix_used = True
if "=" in i:
(key, val) = i.split("=", 1)
else:
key = i
val = None
if prefix_used:
self._args_with_prefix.add(key)
# Some duplicate args create a space separated string
if key in CMDLINE_APPEND and self._data.get(key, None):
if val:
self._data[key] = self._data[key] + " " + val
# Some arguments can contain spaces so adding them in one string is not that helpful
elif key in CMDLINE_LIST:
if val:
if not self._data.get(key, None):
self._data[key] = []
self._data[key].append(val)
else:
self._data[key] = val
def is_enabled(self, arg):
"""Return boolean value for the given argument.
Rules:
- 0, off, not present -> False
- the rest -> True
"""
# None is stored when arg is present but had no value when parsing.
# So the "miss" value must be something else.
val = self._data.get(arg, False)
if val in ["0", "off", False]:
return False
else:
return True
def get(self, arg, default=None):
"""Return the value of the given argument.
Propagates the call verbatim to the underlying dictionary.
"""
return self._data.get(arg, default)
def __contains__(self, arg):
"""Check for presence of an argument.
Propagates the call verbatim to the underlying dictionary.
"""
return arg in self._data
def items(self):
"""Return an iterator over all arguments.
Propagates the call verbatim to the underlying dictionary.
"""
return self._data.items()
def items_raw(self):
"""Return an iterator over all arguments in their raw form (with prefixes).
TODO: DO NOT USE THIS METHOD! This workaround will be removed
when lack of 'inst.' prefix is not supported.
"""
for key, val in self._data.items():
if key in self._args_with_prefix:
yield ("{}{}".format(BOOT_ARG_PREFIX, key), val)
continue
yield (key, val)
kernel_arguments = KernelArguments.from_defaults()