From: "Samantha N. Bueno" <sbueno+anaconda(a)redhat.com>
The two dependencies we're eliminating here:
blivet.osinstall.StorageDiscoveryConfig
blivet.osinstall.find_existing_installations
This has the added benefit of eliminating depedence on pykickstart.constants.
Unfortunately this means changing a lot of stuff all at once, but these
are mostly moves without any changes. Stuff that's now out of
blivet.blivet.Blivet and now in blivet.osinstall.InstallerStorage:
autopart_type (attr)
_free_space_snapshot (attr)
free_space_snapshot (prop)
create_free_space_snapshot
Things which were changed in blivet.blivet.Blivet to eliminate dependence
on anything in blivet.osinstall:
reset
get_free_space
Those two methods exist as they originally were in
blivet.osinstall.InstallerStorage now.
InstallerStorage also handles protected devices now as well, so all of
that logic has been moved out of blivet.populator.populator and into
this class. Namely, three functions have been moved to InstallerStorage:
_resolve_protected_device_specs
_find_live_backing_device
_mark_protected_device
iSCSI, FCoE, and zFCP startup/config writes now take place in
InstallerStorage.
---
blivet/autopart.py | 4 +-
blivet/blivet.py | 82 ++-----------
blivet/osinstall.py | 273 ++++++++++++------------------------------
blivet/populator/populator.py | 47 --------
4 files changed, 87 insertions(+), 319 deletions(-)
diff --git a/blivet/autopart.py b/blivet/autopart.py
index a75c567..347c1bc 100644
--- a/blivet/autopart.py
+++ b/blivet/autopart.py
@@ -110,8 +110,8 @@ def _get_candidate_disks(storage):
for a default-sized (500MiB) partition. They must also be in
:attr:`StorageDiscoveryConfig.clear_part_disks` if it is non-empty.
- :param storage: a Blivet instance
- :type storage: :class:`~.Blivet`
+ :param storage: an InstallerStorage instance
+ :type storage: :class:`~.osinstall.InstallerStorage`
:returns: a list of partitioned disks with at least 500MiB of free space
:rtype: list of :class:`~.devices.StorageDevice`
"""
diff --git a/blivet/blivet.py b/blivet/blivet.py
index adb4d4f..4c5741d 100644
--- a/blivet/blivet.py
+++ b/blivet/blivet.py
@@ -27,8 +27,6 @@
import time
import functools
-from pykickstart.constants import AUTOPART_TYPE_LVM
-
from .storage_log import log_method_call, log_exception_info
from .devices import BTRFSSubVolumeDevice, BTRFSVolumeDevice
from .devices import LVMLogicalVolumeDevice, LVMVolumeGroupDevice
@@ -45,11 +43,7 @@
from .flags import flags
from .platform import platform as _platform
from .formats import get_format
-from .osinstall import StorageDiscoveryConfig find_existing_installations
from . import arch
-from .iscsi import iscsi
-from .fcoe import fcoe
-from .zfcp import zfcp
from . import devicefactory
from . import get_bootloader, get_sysroot, short_product_name, __version__
from .threads import SynchronizedMeta
@@ -70,13 +64,10 @@ def __init__(self, ksdata=None):
self.ksdata = ksdata
self._bootloader = None
- self.config = StorageDiscoveryConfig()
-
# storage configuration variables
self.do_autopart = False
self.clear_part_choice = None
self.encrypted_autopart = False
- self.autopart_type = AUTOPART_TYPE_LVM
self.encryption_passphrase = None
self.encryption_cipher = None
self.escrow_certificates = {}
@@ -105,7 +96,6 @@ def __init__(self, ksdata=None):
disk_images=self.disk_images)
self.roots = []
self.services = set()
- self._free_space_snapshot = None
def do_it(self, callbacks=None):
"""
@@ -148,20 +138,6 @@ def reset(self, cleanup_only=False):
about the cleanup_only keyword argument.
"""
log.info("resetting Blivet (version %s) instance %s", __version__,
self)
- if flags.installer_mode:
- # save passphrases for luks devices so we don't have to reprompt
- self.encryption_passphrase = None
- for device in self.devices:
- if device.format.type == "luks" and device.format.exists:
- self.save_passphrase(device)
-
- if self.ksdata:
- self.config.update(self.ksdata)
-
- if flags.installer_mode and not flags.image_install:
- iscsi.startup()
- fcoe.startup()
- zfcp.startup()
self.devicetree.reset(passphrase=self.encryption_passphrase,
luks_dict=self.__luks_devs,
@@ -176,14 +152,6 @@ def reset(self, cleanup_only=False):
# no longer in the tree
self.bootloader.reset()
- self.roots = []
- if flags.installer_mode:
- self.roots = find_existing_installations(self.devicetree)
- self.dump_state("initial")
-
- if not flags.installer_mode:
- self.devicetree.handle_nodev_filesystems()
-
self.update_bootloader_disk_list()
@property
@@ -434,23 +402,20 @@ def remove_empty_extended_partitions(self):
extended = self.devicetree.get_device_by_name(extended_name)
self.destroy_device(extended)
- def get_free_space(self, disks=None, clear_part_type=None):
+ def get_free_space(self, disks=None, partitions=None):
""" Return a dict with free space info for each disk.
The dict values are 2-tuples: (disk_free, fs_free). fs_free is
space available by shrinking filesystems. disk_free is space not
allocated to any partition.
- disks and clear_part_type allow specifying a set of disks other than
- self.disks and a clear_part_type value other than
- self.config.clear_part_type.
+ disks and partitions allow specifying a set of disks other than
+ self.disks and partition values other than self.parttions.
:keyword disks: overrides :attr:`disks`
:type disks: list
- :keyword clear_part_type: overrides :attr:`self.config.clear_part_type`
- :type clear_part_type: int
- :returns: dict with disk name keys and tuple (disk, fs) free values
- :rtype: dict
+ :keyword partitions: overrides :attr:`partitions`
+ :type partitions: list
.. note::
@@ -460,31 +425,17 @@ def get_free_space(self, disks=None, clear_part_type=None):
if disks is None:
disks = self.disks
- if clear_part_type is None:
- clear_part_type = self.config.clear_part_type
+ if partitions is None:
+ partitions = self.partitions
free = {}
for disk in disks:
- should_clear = self.should_clear(disk, clear_part_type=clear_part_type,
- clear_part_disks=[disk.name])
- if should_clear:
- free[disk.name] = (disk.size, Size(0))
- continue
-
disk_free = Size(0)
fs_free = Size(0)
if disk.partitioned:
disk_free = disk.format.free
- for partition in [p for p in self.partitions if p.disk == disk]:
- # only check actual filesystems since lvm &c require a bunch of
- # operations to translate free filesystem space into free disk
- # space
- should_clear = self.should_clear(partition,
- clear_part_type=clear_part_type,
- clear_part_disks=[disk.name])
- if should_clear:
- disk_free += partition.size
- elif hasattr(partition.format, "free"):
+ for partition in (p for p in partitions if p.disk == disk):
+ if hasattr(partition.format, "free"):
fs_free += partition.format.free
elif hasattr(disk.format, "free"):
fs_free = disk.format.free
@@ -1064,9 +1015,6 @@ def write(self):
if not os.path.isdir("%s/etc" % get_sysroot()):
os.mkdir("%s/etc" % get_sysroot())
- iscsi.write(get_sysroot(), self)
- fcoe.write(get_sysroot())
- zfcp.write(get_sysroot())
self.write_dasd_conf(get_sysroot())
def write_dasd_conf(self, root):
@@ -1366,15 +1314,3 @@ def copy(self):
log.debug("finished Blivet copy")
return new
-
- @property
- def free_space_snapshot(self):
- # if no snapshot is available, do it now and return it
- self._free_space_snapshot = self._free_space_snapshot or self.get_free_space()
-
- return self._free_space_snapshot
-
- def create_free_space_snapshot(self):
- self._free_space_snapshot = self.get_free_space()
-
- return self._free_space_snapshot
diff --git a/blivet/osinstall.py b/blivet/osinstall.py
index 3289725..aa369eb 100644
--- a/blivet/osinstall.py
+++ b/blivet/osinstall.py
@@ -31,9 +31,9 @@
from gi.repository import BlockDev as blockdev
-from pykickstart.constants import CLEARPART_TYPE_NONE, CLEARPART_TYPE_LINUX,
CLEARPART_TYPE_ALL, CLEARPART_TYPE_LIST
+from pykickstart.constants import AUTOPART_TYPE_LVM, CLEARPART_TYPE_NONE,
CLEARPART_TYPE_LINUX, CLEARPART_TYPE_ALL, CLEARPART_TYPE_LIST
-from . import util
+from . import util, __version__
from . import get_sysroot, get_target_physical_root, error_handler, ERROR_RAISE
from .blivet import Blivet
@@ -45,9 +45,13 @@
from .formats import get_device_format_class
from .formats import get_format
from .flags import flags
+from .iscsi import iscsi
+from .fcoe import fcoe
+from .zfcp import zfcp
from .platform import platform as _platform
from .platform import EFI
from .size import Size
+from .udev import resolve_devspec
from .i18n import _
@@ -313,7 +317,7 @@ def update(self, ksdata):
self.clear_part_type = ksdata.clearpart.type
self.clear_part_disks = ksdata.clearpart.drives[:]
self.clear_part_devices = ksdata.clearpart.devices[:]
- self.initialize_disks = ksdata.clearpart.init_all
+ self.initialize_disks = ksdata.clearpart.initAll
self.zero_mbr = ksdata.zerombr.zerombr
@@ -1111,25 +1115,16 @@ def __init__(self, ksdata=None):
self.autopart_type = AUTOPART_TYPE_LVM
self.__luks_devs = {}
-
- # these will both be empty until our reset method gets called
- # instantiate our own devicetree here to override the default created
- # in Blivet so that protected_dev_specs gets handled
- self.devicetree = DeviceTree(passphrase=self.encryption_passphrase,
- luks_dict=self.__luks_devs,
- ignored_disks=self.ignored_disks,
- exclusive_disks=self.exclusive_disks,
- disk_images=self.disk_images,
-
protected_dev_specs=self.config.protected_dev_specs)
self.fsset = FSSet(self.devicetree)
self._free_space_snapshot = None
+ self.live_backing_device = None
def do_it(self, callbacks=None):
"""
Commit queued changes to disk.
:param callbacks: callbacks to be invoked when actions are executed
- :type callbacks: return value of the :func:`~.callbacks.create_new_callbacks_
+ :type callbacks: return value of the
:func:`~.callbacks.create_new_callbacks_register`
"""
super().do_it(callbacks=callbacks)
@@ -1217,22 +1212,18 @@ def reset(self, cleanup_only=False):
fcoe.startup()
zfcp.startup()
- self.devicetree.reset(passphrase=self.encryption_passphrase,
- luks_dict=self.__luks_devs,
- ignored_disks=self.ignored_disks,
- exclusive_disks=self.exclusive_disks,
- disk_images=self.disk_images,
- protected_dev_specs=self.config.protected_dev_specs)
- self.devicetree.populate(cleanup_only=cleanup_only)
- self.fsset = FSSet(self.devicetree)
- self.edd_dict = get_edd_dict(self.partitioned)
- self.devicetree.edd_dict = self.edd_dict
- if self.bootloader:
- # clear out bootloader attributes that refer to devices that are
- # no longer in the tree
- self.bootloader.reset()
+ super().reset(cleanup_only=cleanup_only)
+
+ # protected device handling
+ self.protected_dev_names = []
+ self._resolve_protected_device_specs()
+ self._find_live_backing_device()
+ for devname in self.protected_dev_names:
+ dev = self.devicetree.get_device_by_name(devname)
+ self._mark_protected_device(dev)
+
if self.ksdata:
- self.config.updates(self.ksdata)
+ self.config.update(self.ksdata)
self.roots = []
if flags.installer_mode:
self.roots = find_existing_installations(self.devicetree)
@@ -1243,6 +1234,46 @@ def reset(self, cleanup_only=False):
self.update_bootloader_disk_list()
+ def _resolve_protected_device_specs(self):
+ """ Resolve the protected device specs to device names.
"""
+ for spec in self.config.protected_dev_specs:
+ name = resolve_devspec(spec)
+ log.debug("protected device spec %s resolved to %s", spec, name)
+ if name:
+ self.protected_dev_names.append(name)
+
+ def _find_live_backing_device(self):
+ # FIXME: the backing dev for the live image can't be used as an
+ # install target. note that this is a little bit of a hack
+ # since we're assuming that /run/initramfs/live will exist
+ for mnt in open("/proc/mounts").readlines():
+ if " /run/initramfs/live " not in mnt:
+ continue
+
+ live_device_name = mnt.split()[0].split("/")[-1]
+ log.info("%s looks to be the live device; marking as protected",
+ live_device_name)
+ self.protected_dev_names.append(live_device_name)
+ self.live_backing_device = live_device_name
+ break
+
+ def _mark_protected_device(self, device):
+ """
+ If this device is protected, mark it as such now. Once the tree
+ has been populated, devices' protected attribute is how we will
+ identify protected devices.
+
+ :param :class: `blivet.devices.storage.StorageDevice` device: device to
+ mark as protected
+ """
+ if device.name in self.protected_dev_names:
+ device.protected = True
+ # if this is the live backing device we want to mark its parents
+ # as protected also
+ if device.name == self.live_backing_device:
+ for parent in device.parents:
+ parent.protected = True
+
def get_free_space(self, disks=None, clear_part_type=None):
""" Return a dict with free space info for each disk.
@@ -1465,176 +1496,12 @@ def _update_custom_storage_ksdata(self):
parent = getattr(self.ksdata, list_attr)
parent.dataList().append(data)
- self.fsset = FSSet(self.devicetree)
-
- def reset(self, cleanup_only=False):
- Blivet.reset(self, cleanup_only)
+ self.config = StorageDiscoveryConfig()
+ self.autopart_type = AUTOPART_TYPE_LVM
+ self.__luks_devs = {}
self.fsset = FSSet(self.devicetree)
-
- def write(self):
- Blivet.write(self)
-
- self.fsset.write()
- self.make_mtab()
-
- @property
- def boot_device(self):
- dev = None
- if self.fsset:
- dev = self.mountpoints.get("/boot", self.root_device)
- return dev
-
- @property
- def mountpoints(self):
- return self.fsset.mountpoints
-
- @property
- def root_device(self):
- return self.fsset.root_device
-
- @property
- def file_system_free_space(self):
- """ Combined free space in / and /usr as :class:`~.size.Size`.
"""
- mountpoints = ["/", "/usr"]
- free = Size(0)
- btrfs_volumes = []
- for mountpoint in mountpoints:
- device = self.mountpoints.get(mountpoint)
- if not device:
- continue
-
- # don't count the size of btrfs volumes repeatedly when multiple
- # subvolumes are present
- if isinstance(device, BTRFSSubVolumeDevice):
- if device.volume in btrfs_volumes:
- continue
- else:
- btrfs_volumes.append(device.volume)
-
- if device.format.exists:
- free += device.format.free
- else:
- free += device.format.free_space_estimate(device.size)
-
- return free
- def update_ksdata(self):
- """ Update ksdata to reflect the settings of this Blivet instance.
"""
- if not self.ksdata or not self.mountpoints:
- return
-
- # clear out whatever was there before
- self.ksdata.partition.partitions = []
- self.ksdata.logvol.lvList = []
- self.ksdata.raid.raidList = []
- self.ksdata.volgroup.vgList = []
- self.ksdata.btrfs.btrfsList = []
-
- # iscsi?
- # fcoe?
- # zfcp?
- # dmraid?
-
- # bootloader
-
- # ignoredisk
- if self.ignored_disks:
- self.ksdata.ignoredisk.drives = self.ignored_disks[:]
- elif self.exclusive_disks:
- self.ksdata.ignoredisk.onlyuse = self.exclusive_disks[:]
-
- # autopart
- self.ksdata.autopart.autopart = self.do_autopart
- self.ksdata.autopart.type = self.autopart_type
- self.ksdata.autopart.encrypted = self.encrypted_autopart
-
- # clearpart
- self.ksdata.clearpart.type = self.config.clear_part_type
- self.ksdata.clearpart.drives = self.config.clear_part_disks[:]
- self.ksdata.clearpart.devices = self.config.clear_part_devices[:]
- self.ksdata.clearpart.initAll = self.config.initialize_disks
- if self.ksdata.clearpart.type == CLEARPART_TYPE_NONE:
- # Make a list of initialized disks and of removed partitions. If any
- # partitions were removed from disks that were not completely
- # cleared we'll have to use CLEARPART_TYPE_LIST and provide a list
- # of all removed partitions. If no partitions were removed from a
- # disk that was not cleared/reinitialized we can use
- # CLEARPART_TYPE_ALL.
- self.ksdata.clearpart.devices = []
- self.ksdata.clearpart.drives = []
- fresh_disks = [d.name for d in self.disks if d.partitioned and
- not d.format.exists]
-
- destroy_actions =
self.devicetree.actions.find(action_type="destroy",
-
object_type="device")
-
- cleared_partitions = []
- partial = False
- for action in destroy_actions:
- if action.device.type == "partition":
- if action.device.disk.name not in fresh_disks:
- partial = True
-
- cleared_partitions.append(action.device.name)
-
- if not destroy_actions:
- pass
- elif partial:
- # make a list of removed partitions
- self.ksdata.clearpart.type = CLEARPART_TYPE_LIST
- self.ksdata.clearpart.devices = cleared_partitions
- else:
- # if they didn't partially clear any disks, use the shorthand
- self.ksdata.clearpart.type = CLEARPART_TYPE_ALL
- self.ksdata.clearpart.drives = fresh_disks
-
- if self.do_autopart:
- return
-
- self._update_custom_storage_ksdata()
-
- def _update_custom_storage_ksdata(self):
- """ Update KSData for custom storage. """
-
- # custom storage
- ks_map = {PartitionDevice: ("PartData", "partition"),
- TmpFSDevice: ("PartData", "partition"),
- LVMLogicalVolumeDevice: ("LogVolData", "logvol"),
- LVMVolumeGroupDevice: ("VolGroupData",
"volgroup"),
- MDRaidArrayDevice: ("RaidData", "raid"),
- BTRFSDevice: ("BTRFSData", "btrfs")}
-
- # make a list of ancestors of all used devices
- devices = list(set(a for d in list(self.mountpoints.values()) + self.swaps
- for a in d.ancestors))
-
- # devices which share information with their distinct raw device
- complementary_devices = [d for d in devices if d.raw_device is not d]
-
- devices.sort(key=lambda d: len(d.ancestors))
- for device in devices:
- cls = next((c for c in ks_map if isinstance(device, c)), None)
- if cls is None:
- log.info("omitting ksdata: %s", device)
- continue
-
- class_attr, list_attr = ks_map[cls]
-
- cls = getattr(self.ksdata, class_attr)
- data = cls() # all defaults
-
- complements = [d for d in complementary_devices if d.raw_device is device]
-
- if len(complements) > 1:
- log.warning("omitting ksdata for %s, found too many (%d)
complementary devices", device, len(complements))
- continue
-
- device = complements[0] if complements else device
-
- device.populate_ksdata(data)
-
- parent = getattr(self.ksdata, list_attr)
- parent.dataList().append(data)
+ self._free_space_snapshot = None
def empty_device(self, device):
empty = True
@@ -1875,6 +1742,18 @@ def make_mtab(self):
os.symlink(target, path)
+ @property
+ def free_space_snapshot(self):
+ # if no snapshot is available, do it now and return it
+ self._free_space_snapshot = self._free_space_snapshot or self.get_free_space()
+
+ return self._free_space_snapshot
+
+ def create_free_space_snapshot(self):
+ self._free_space_snapshot = self.get_free_space()
+
+ return self._free_space_snapshot
+
def add_fstab_swap(self, device):
"""
Add swap device to the list of swaps that should appear in the fstab.
diff --git a/blivet/populator/populator.py b/blivet/populator/populator.py
index 54fd53e..7c7d0ce 100644
--- a/blivet/populator/populator.py
+++ b/blivet/populator/populator.py
@@ -74,20 +74,12 @@ def __init__(self, passphrase=None, luks_dict=None,
disk_images=None):
"""
self.reset(passphrase=passphrase, luks_dict=luks_dict, disk_images=disk_images)
- def reset(self, conf=None, passphrase=None, luks_dict=None):
def reset(self, passphrase=None, luks_dict=None, disk_images=None):
self.disk_images = {}
if disk_images:
# this will overwrite self.exclusive_disks
self.set_disk_images(disk_images)
- # protected device specs as provided by the user
- self.protected_dev_specs = getattr(conf, "protected_dev_specs", [])
- self.live_backing_device = None
-
- # names of protected devices at the time of tree population
- self.protected_dev_names = []
-
self.__passphrases = []
if passphrase:
self.__passphrases.append(passphrase)
@@ -246,18 +238,6 @@ def _mark_readonly_device(self, info, device):
util.get_sysfs_attr(udev.device_get_sysfs_path(info), 'ro') ==
'1':
device.readonly = True
- def _mark_protected_device(self, device):
- # If this device is protected, mark it as such now. Once the tree
- # has been populated, devices' protected attribute is how we will
- # identify protected devices.
- if device.name in self.protected_dev_names:
- device.protected = True
- # if this is the live backing device we want to mark its parents
- # as protected also
- if device.name == self.live_backing_device:
- for parent in device.parents:
- parent.protected = True
-
def _update_exclusive_disks(self, device):
# If we just added a multipath or fwraid disk that is in exclusive_disks
# we have to make sure all of its members are in the list too.
@@ -317,7 +297,6 @@ def handle_device(self, info, update_orig_fmt=False):
log.info("got device: %r", device)
self._mark_readonly_device(info, device)
- self._mark_protected_device(device)
self._update_exclusive_disks(device)
# now handle the device's formatting
@@ -465,29 +444,6 @@ def populate(self, cleanup_only=False):
if flags.installer_mode:
self.teardown_all()
- def _resolve_protected_device_specs(self):
- # resolve the protected device specs to device names
- for spec in self.protected_dev_specs:
- name = udev.resolve_devspec(spec)
- log.debug("protected device spec %s resolved to %s", spec, name)
- if name:
- self.protected_dev_names.append(name)
-
- def _find_live_backing_device(self):
- # FIXME: the backing dev for the live image can't be used as an
- # install target. note that this is a little bit of a hack
- # since we're assuming that /run/initramfs/live will exist
- for mnt in open("/proc/mounts").readlines():
- if " /run/initramfs/live " not in mnt:
- continue
-
- live_device_name = mnt.split()[0].split("/")[-1]
- log.info("%s looks to be the live device; marking as protected",
- live_device_name)
- self.protected_dev_names.append(live_device_name)
- self.live_backing_device = live_device_name
- break
-
def _populate(self):
log.info("DeviceTree.populate: ignored_disks is %s ; exclusive_disks is
%s",
self.ignored_disks, self.exclusive_disks)
@@ -499,9 +455,6 @@ def _populate(self):
self.setup_disk_images()
- self._resolve_protected_device_specs()
- self._find_live_backing_device()
-
old_devices = {}
# Now, loop and scan for devices that have appeared since the two above
--
To view this commit on github, visit
https://github.com/rhinstaller/blivet/commit/4898e15e746cb37cd8debf553a69...