Mini Shell
#
# 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.
#
# Author(s): Vendula Poncova <vponcova@redhat.com>
#
from enum import Enum
from blivet.size import Size
from pykickstart.constants import AUTOPART_TYPE_PLAIN, AUTOPART_TYPE_BTRFS, AUTOPART_TYPE_LVM, \
AUTOPART_TYPE_LVM_THINP
from pyanaconda.core.configuration.base import Section
class PartitioningScheme(Enum):
"""Type of the default partitioning scheme."""
PLAIN = AUTOPART_TYPE_PLAIN
BTRFS = AUTOPART_TYPE_BTRFS
LVM = AUTOPART_TYPE_LVM
LVM_THINP = AUTOPART_TYPE_LVM_THINP
@classmethod
def from_name(cls, value):
"""Convert the given value into a partitioning scheme."""
try:
member = cls.__members__[value]
return member.value
except KeyError:
pass
raise ValueError("'{}' is not a valid partitioning scheme".format(value))
class StorageSection(Section):
"""The Storage section."""
@property
def dmraid(self):
"""Enable dmraid usage during the installation."""
return self._get_option("dmraid", bool)
@property
def ibft(self):
"""Enable iBFT usage during the installation."""
return self._get_option("ibft", bool)
@property
def gpt(self):
"""Do you prefer creation of GPT disk labels?"""
return self._get_option("gpt", bool)
@property
def multipath_friendly_names(self):
"""Use user friendly names for multipath devices.
Tell multipathd to use user friendly names when naming devices
during the installation.
"""
return self._get_option("multipath_friendly_names", bool)
@property
def allow_imperfect_devices(self):
"""Do you want to allow imperfect devices?
Imperfect devices are for example degraded mdraid arrays.
This option should be enabled only in the rescue mode.
"""
return self._get_option("allow_imperfect_devices", bool)
@property
def file_system_type(self):
"""Default file system type.
If no type is specified, we will use whatever Blivet uses by default.
For example: xfs
"""
return self._get_option("file_system_type", str)
@property
def default_scheme(self):
"""Default partitioning scheme.
Valid values:
0 PLAIN Create standard partitions.
1 BTRFS Use the Btrfs scheme.
2 LVM Use the LVM scheme.
3 LVM_THINP Use LVM Thin Provisioning.
:return: a partitioning scheme
"""
return self._get_option("default_scheme", PartitioningScheme.from_name)
@property
def luks_version(self):
"""Default version of LUKS.
Valid values:
luks1 Use version 1 by default.
luks2 Use version 2 by default.
"""
value = self._get_option("luks_version", str)
if value not in ("luks1", "luks2"):
raise ValueError("Invalid value: {}".format(value))
return value
@property
def default_partitioning(self):
"""Default partitioning.
Returns a list of dictionaries with mount point attributes.
The name of the mount point is represented by the attribute
'name' in the dictionary representation.
Valid attributes:
name The name of the mount point.
size The size of the mount point.
min The size will grow from min size to max size.
max The max size is unlimited by default.
free The required available space.
:return: a list of dictionaries with mount point attributes
"""
return self._get_option("default_partitioning", self._convert_partitioning)
def _convert_partitioning(self, value):
"""Convert a partitioning string into a list of dictionaries."""
return list(map(self._convert_partitioning_line, value.strip().split("\n")))
@classmethod
def _convert_partitioning_line(cls, line):
"""Convert a partitioning line into a dictionary."""
# Parse the line.
name, raw_attrs = cls._split_string(line)
# Split the attributes and skip empty strings (split
# always returns at least one item, an empty string).
raw_attrs = raw_attrs.strip("()").split(",")
raw_attrs = map(cls._split_string, filter(None, raw_attrs))
# Generate the dictionary.
attrs = {"name": name}
for name, value in raw_attrs:
if value and name in ("size", "min", "max", "free"):
# Handle a size attribute.
attrs[name] = Size(value)
else:
# Handle an invalid attribute.
raise ValueError("Invalid attribute: " + name)
# Validate the dictionary.
cls._validate_mount_point_attributes(attrs)
return attrs
@staticmethod
def _validate_mount_point_attributes(attrs):
"""Validate the dictionary with mount point attributes."""
if not attrs.get("name"):
raise ValueError("The mount point is not specified.")
if attrs.get("name") != "swap" and not attrs.get("name").startswith("/"):
raise ValueError("The mount point is not valid.")
if attrs.get("size") and attrs.get("min"):
raise ValueError("Only one of the attributes 'size' and 'min' can be set.")
if attrs.get("max") and not attrs.get("min"):
raise ValueError("The attribute 'max' cannot be set without 'min'.")
@staticmethod
def _split_string(value):
"""Split the given value into two strings."""
items = value.strip().split(maxsplit=1)
while len(items) < 2:
items.append("")
return items