anaconda/anaconda-40.22.3.13/pyanaconda/modules/storage/partitioning/manual/manual_module.py
2024-11-14 21:39:56 -08:00

189 lines
6.7 KiB
Python

#
# Manual partitioning module.
#
# 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.
#
from blivet.size import Size
from pyanaconda.anaconda_loggers import get_module_logger
from pyanaconda.core.signal import Signal
from pyanaconda.modules.common.structures.partitioning import MountPointRequest
from pyanaconda.modules.storage.partitioning.base import PartitioningModule
from pyanaconda.modules.storage.partitioning.constants import PartitioningMethod
from pyanaconda.modules.storage.partitioning.manual.manual_interface import \
ManualPartitioningInterface
from pyanaconda.modules.storage.partitioning.manual.manual_partitioning import \
ManualPartitioningTask
log = get_module_logger(__name__)
class ManualPartitioningModule(PartitioningModule):
"""The manual partitioning module."""
def __init__(self):
"""Initialize the module."""
super().__init__()
self.requests_changed = Signal()
self._requests = list()
@property
def partitioning_method(self):
"""Type of the partitioning method."""
return PartitioningMethod.MANUAL
def for_publication(self):
"""Return a DBus representation."""
return ManualPartitioningInterface(self)
def process_kickstart(self, data):
"""Process the kickstart data."""
requests = []
for mount_data in data.mount.mount_points:
request = MountPointRequest()
request.mount_point = mount_data.mount_point
request.device_spec = mount_data.device
request.reformat = mount_data.reformat
request.format_type = mount_data.format
request.format_options = mount_data.mkfs_opts
request.mount_options = mount_data.mount_opts
requests.append(request)
self.set_requests(requests)
def setup_kickstart(self, data):
"""Setup the kickstart data."""
data_list = []
for request in self.requests:
mount_data = data.MountData()
mount_data.mount_point = request.mount_point
mount_data.device = request.device_spec
mount_data.reformat = request.reformat
mount_data.format = request.format_type
mount_data.mkfs_opts = request.format_options
mount_data.mount_opts = request.mount_options
data_list.append(mount_data)
data.mount.mount_points = data_list
@property
def requests(self):
"""A list of mount point requests."""
return self._requests
def set_requests(self, requests):
"""Set the list of mount point requests.
:param requests: a list of instances of MountPointRequest
"""
self._requests = requests
self.requests_changed.emit()
log.debug("Requests are set to '%s'.", requests)
def gather_requests(self):
"""Gather all mount point requests.
Return mount point requests for all usable devices. If there is
a defined request for the given device, we will use it. Otherwise,
we will generate a new request.
:return: a list of instances of MountPointRequest
"""
available_requests = set(self.requests)
requests = []
for device in self._iterate_usable_devices():
# Find an existing request.
request = self._find_request_for_device(device, available_requests)
# And use it only once.
if request:
available_requests.remove(request)
# Otherwise, create a new request.
else:
request = self._create_request_for_device(device)
# Add the request for this device.
requests.append(request)
return requests
def _iterate_usable_devices(self):
"""Iterate over all usable devices.
:return: an iterator over Blivet's devices
"""
selected_disks = set(self._selected_disks)
for device in self.storage.devicetree.devices:
if not device.isleaf and not device.raw_device.type == "btrfs subvolume":
continue
# We don't want to allow to use snapshots in mount point assignment.
if device.raw_device.type == "btrfs snapshot":
continue
# Is the device usable?
if device.protected or device.size == Size(0):
continue
# All device's disks have to be in selected disks.
if selected_disks and not selected_disks.issuperset({d.name for d in device.disks}):
continue
yield device
def _find_request_for_device(self, device, requests):
"""Find a mount point request for the given device.
:param device: a Blivet's device object
:param requests: a list of requests to search
:return: an instance of MountPointRequest or None
"""
for request in requests:
if device is self.storage.devicetree.resolve_device(request.device_spec):
return request
return None
def _create_request_for_device(self, device):
"""Create a mount point request for the given device.
:param device: a Blivet's device object
:return: an instance of MountPointRequest
"""
request = MountPointRequest()
request.device_spec = device.name
request.format_type = device.format.type or ""
request.reformat = False
if device.format.mountable:
if device.format.mountpoint:
request.mount_point = device.format.mountpoint
if device.format.mountopts:
request.mount_options = device.format.mountopts
return request
def configure_with_task(self):
"""Schedule the partitioning actions."""
return ManualPartitioningTask(
self.storage,
self.requests
)