From d53fee8f0b40c38d0bfdfaee575fe8eea0465f63 Mon Sep 17 00:00:00 2001
From: "Samantha N. Bueno" <sbueno+anaconda@redhat.com>
Date: Mon, 28 Mar 2016 15:27:19 -0400
Subject: [PATCH 5/7] Get rid of blivet.blivet's last deps on blivet.osinstall

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.InstallerStorageConfig:
    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.InstallerStorageConfig now.

InstallerStorageConfig instantiates its own devicetree now. This is mostly
to keep track of all those installer-specific goodies (e.g. protected_dev_spacs).
As a result of us now passing that attr in, modified headers in devicetree and
populator init/reset methods to optionally handle this attr.

iSCSI, FCoE, and zFCP startup/config writes now take place in
InstallerStorageConfig.
---
 blivet/autopart.py            |   4 +-
 blivet/blivet.py              |  82 ++---------------
 blivet/devicetree.py          |   8 +-
 blivet/osinstall.py           | 205 +++++++-----------------------------------
 blivet/populator/populator.py |   9 +-
 5 files changed, 53 insertions(+), 255 deletions(-)

diff --git a/blivet/autopart.py b/blivet/autopart.py
index a75c567..a530a7c 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 InstallerStorageConfig instance
+        :type storage: :class:`~.osinstall.InstallerStorageConfig`
         :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 a3b7407..ca403e0 100644
--- a/blivet/blivet.py
+++ b/blivet/blivet.py
@@ -28,8 +28,6 @@ import time
 import parted
 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
@@ -46,11 +44,7 @@ from .formats import get_default_filesystem_type
 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
@@ -71,13 +65,10 @@ class Blivet(object, metaclass=SynchronizedMeta):
         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 = {}
@@ -106,7 +97,6 @@ class Blivet(object, metaclass=SynchronizedMeta):
                                      disk_images=self.disk_images)
         self.roots = []
         self.services = set()
-        self._free_space_snapshot = None
 
     def do_it(self, callbacks=None):
         """
@@ -207,20 +197,6 @@ class Blivet(object, metaclass=SynchronizedMeta):
             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,
@@ -235,14 +211,6 @@ class Blivet(object, metaclass=SynchronizedMeta):
             # 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
@@ -493,23 +461,20 @@ class Blivet(object, metaclass=SynchronizedMeta):
                 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::
 
@@ -519,31 +484,17 @@ class Blivet(object, metaclass=SynchronizedMeta):
         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
@@ -1123,9 +1074,6 @@ class Blivet(object, metaclass=SynchronizedMeta):
         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):
@@ -1425,15 +1373,3 @@ class Blivet(object, metaclass=SynchronizedMeta):
 
         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/devicetree.py b/blivet/devicetree.py
index d10d36d..911c949 100644
--- a/blivet/devicetree.py
+++ b/blivet/devicetree.py
@@ -899,12 +899,12 @@ class DeviceTreeBase(object, metaclass=SynchronizedMeta):
 
 
 class DeviceTree(DeviceTreeBase, PopulatorMixin, EventHandlerMixin):
-    def __init__(self, passphrase=None, luks_dict=None, ignored_disks=None, exclusive_disks=None, disk_images=None):
+    def __init__(self, passphrase=None, luks_dict=None, ignored_disks=None, exclusive_disks=None, disk_images=None, protected_dev_specs=None):
         DeviceTreeBase.__init__(self, ignored_disks=ignored_disks, exclusive_disks=exclusive_disks)
-        PopulatorMixin.__init__(self, passphrase=passphrase, luks_dict=luks_dict, disk_images=disk_images)
+        PopulatorMixin.__init__(self, passphrase=passphrase, luks_dict=luks_dict, disk_images=disk_images, protected_dev_specs=protected_dev_specs)
         EventHandlerMixin.__init__(self)
 
     # pylint: disable=arguments-differ
-    def reset(self, passphrase=None, luks_dict=None, ignored_disks=None, exclusive_disks=None, disk_images=None):
+    def reset(self, passphrase=None, luks_dict=None, ignored_disks=None, exclusive_disks=None, disk_images=None, protected_dev_specs=None):
         DeviceTreeBase.reset(self, ignored_disks=ignored_disks, exclusive_disks=exclusive_disks)
-        PopulatorMixin.reset(self, passphrase=passphrase, luks_dict=luks_dict, disk_images=disk_images)
+        PopulatorMixin.reset(self, passphrase=passphrase, luks_dict=luks_dict, disk_images=disk_images, protected_dev_specs=protected_dev_specs)
diff --git a/blivet/osinstall.py b/blivet/osinstall.py
index 75f67c4..d110782 100644
--- a/blivet/osinstall.py
+++ b/blivet/osinstall.py
@@ -31,9 +31,9 @@ gi.require_version("BlockDev", "1.0")
 
 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
@@ -41,10 +41,15 @@ from .storage_log import log_exception_info
 from .devices import FileDevice, NFSDevice, NoDevice, OpticalDevice, NetworkStorageDevice, DirectoryDevice
 from .devices import PartitionDevice, BTRFSSubVolumeDevice, TmpFSDevice, LVMLogicalVolumeDevice, LVMVolumeGroupDevice
 from .devices import MDRaidArrayDevice, BTRFSDevice
+from .devicelibs.edd import get_edd_dict
+from .devicetree import DeviceTree
 from .errors import FSTabTypeMismatchError, UnrecognizedFSTabEntryError, StorageError, FSResizeError, FormatResizeError, UnknownSourceDeviceError
 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
@@ -313,7 +318,7 @@ class StorageDiscoveryConfig(object):
         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
 
 
@@ -1163,7 +1168,7 @@ class InstallerStorageConfig(Blivet):
             # no longer in the tree
             self.bootloader.reset()
         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)
@@ -1395,176 +1400,22 @@ class InstallerStorageConfig(Blivet):
             parent = getattr(self.ksdata, list_attr)
             parent.dataList().append(data)
 
-        self.fsset = FSSet(self.devicetree)
+        self.config = StorageDiscoveryConfig()
+        self.autopart_type = AUTOPART_TYPE_LVM
 
-    def reset(self, cleanup_only=False):
-        Blivet.reset(self, cleanup_only)
+        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)
-
-    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
@@ -1805,6 +1656,18 @@ class InstallerStorageConfig(Blivet):
 
         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..8661efd 100644
--- a/blivet/populator/populator.py
+++ b/blivet/populator/populator.py
@@ -63,7 +63,7 @@ def parted_exn_handler(exn_type, exn_options, exn_msg):
 
 
 class PopulatorMixin(object, metaclass=SynchronizedMeta):
-    def __init__(self, passphrase=None, luks_dict=None, disk_images=None):
+    def __init__(self, passphrase=None, luks_dict=None, disk_images=None, protected_dev_specs=None):
         """
             :keyword passphrase: default LUKS passphrase
             :keyword luks_dict: a dict with UUID keys and passphrase values
@@ -72,17 +72,16 @@ class PopulatorMixin(object, metaclass=SynchronizedMeta):
             :type list: dict
 
         """
-        self.reset(passphrase=passphrase, luks_dict=luks_dict, disk_images=disk_images)
+        self.reset(passphrase=passphrase, luks_dict=luks_dict, disk_images=disk_images, protected_dev_specs=protected_dev_specs)
 
-    def reset(self, conf=None, passphrase=None, luks_dict=None):
-    def reset(self, passphrase=None, luks_dict=None, disk_images=None):
+    def reset(self, passphrase=None, luks_dict=None, disk_images=None, protected_dev_specs=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.protected_dev_specs = protected_dev_specs
         self.live_backing_device = None
 
         # names of protected devices at the time of tree population
-- 
2.7.4

