146 lines
6.1 KiB
Python
146 lines
6.1 KiB
Python
#
|
|
# 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
|