# # Configuration of the disk initialization. # # Copyright (C) 2019 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 parted from blivet.devices import PartitionDevice from pyanaconda.anaconda_loggers import get_module_logger from pyanaconda.core.constants import CLEAR_PARTITIONS_DEFAULT, CLEAR_PARTITIONS_NONE, \ CLEAR_PARTITIONS_LINUX, CLEAR_PARTITIONS_ALL, CLEAR_PARTITIONS_LIST log = get_module_logger(__name__) _all__ = ["DiskInitializationConfig"] class DiskInitializationConfig(object): """Configuration of the disk initialization.""" def __init__(self): self.initialization_mode = CLEAR_PARTITIONS_DEFAULT self.drives_to_clear = [] self.devices_to_clear = [] self.initialize_labels = False self.format_unrecognized = False self.clear_non_existent = False def can_remove(self, storage, device): """Can the given device be cleared based on the config? :param storage: an instance of the Blivet's storage :param device: an instance of the device we want to clear :return: True or False """ for disk in device.disks: # this will not include disks with hidden formats like multipath # and firmware raid member disks if self.drives_to_clear and disk.name not in self.drives_to_clear: return False if not self.clear_non_existent: if (device.is_disk and not device.format.exists) or \ (not device.is_disk and not device.exists): return False # the only devices we want to clear when initialization_mode is # CLEAR_PARTITIONS_NONE are uninitialized disks, or disks with no # partitions, in drives_to_clear, and then only when we have been asked # to initialize disks as needed if self.initialization_mode in [CLEAR_PARTITIONS_NONE, CLEAR_PARTITIONS_DEFAULT]: if not self.initialize_labels or not device.is_disk: return False if not device.is_empty: return False if isinstance(device, PartitionDevice): # Never clear the special first partition on a Mac disk label, as # that holds the partition table itself. # Something similar for the third partition on a Sun disklabel. if device.is_magic: return False # We don't want to fool with extended partitions, freespace, &c if not device.is_primary and not device.is_logical: return False if self.initialization_mode == CLEAR_PARTITIONS_LINUX and \ not device.format.linux_native and \ not device.get_flag(parted.PARTITION_LVM) and \ not device.get_flag(parted.PARTITION_RAID) and \ not device.get_flag(parted.PARTITION_SWAP): return False elif device.is_disk: if device.partitioned and self.initialization_mode != CLEAR_PARTITIONS_ALL: # if initialization_mode is not CLEAR_PARTITIONS_ALL but we'll still be # removing every partition from the disk, return True since we # will want to be able to create a new disklabel on this disk if not device.is_empty: return False # Never clear disks with hidden formats if device.format.hidden: return False # When initialization_mode is CLEAR_PARTITIONS_LINUX and a disk has non- # linux whole-disk formatting, do not clear it. The exception is # the case of an uninitialized disk when we've been asked to # initialize disks as needed if (self.initialization_mode == CLEAR_PARTITIONS_LINUX and not ((self.initialize_labels and device.is_empty) or (not device.partitioned and device.format.linux_native))): return False # Don't clear devices holding install media. descendants = storage.devicetree.get_dependent_devices(device) if device.protected or any(d.protected for d in descendants): return False if self.initialization_mode == CLEAR_PARTITIONS_LIST and \ device.name not in self.devices_to_clear: return False return True def can_initialize(self, storage, disk): """Can the given disk be initialized based on the config? :param storage: an instance of the Blivet's storage :param disk: an instance of the disk we want to format :return: True or False """ log.debug("Can %s be initialized?", disk.name) # Skip protected and readonly disks. if disk.protected: log.debug("A protected disk cannot be initialized.") return False # Initialize disks with unrecognized formatting. if self.format_unrecognized and disk.format.type is None: log.debug("A disk with unrecognized formatting can be initialized.") return True # Initialize disks that were removed. if self.can_remove(storage, disk): log.debug("The clearable disk can be initialized.") return True log.debug("The disk cannot be initialized.") return False