# # 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 # 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 from pyanaconda.core.configuration.utils import split_name_and_attributes 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] # pylint: disable=unsubscriptable-object return member.value except KeyError: pass raise ValueError("'{}' is not a valid partitioning scheme".format(value)) class StorageSection(Section): """The Storage section.""" @property def ibft(self): """Enable iBFT usage during the installation.""" return self._get_option("ibft", 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 gpt_discoverable_partitions(self): """Use GPT discoverable partition type IDs, if possible. Tell Blivet to do this. """ return self._get_option("gpt_discoverable_partitions", 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 btrfs_compression(self): """BTRFS compression setting. Specifies the compression algorithm and level used when mounting Btrfs partitions. Defaults to None. For example: "zstd:1" """ return self._get_option("btrfs_compression", str) or None @property def disk_label_type(self): """Default disk label type. Valid values: gpt Prefer creation of GPT disk labels. mbr Prefer creation of MBR disk labels. If no type is specified, we will use whatever Blivet uses by default. :return: a string with the disk label type """ return self._get_option("disk_label_type", str) @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. btrfs The mount point will be created only for the Btrfs scheme :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 = split_name_and_attributes(line) # Generate the dictionary. attrs = {"name": name} for name, value in raw_attrs.items(): if not value and name in ("btrfs", ): # Handle a boolean attribute. attrs[name] = True elif 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'.")