From 03a6405cf4623a95d5ec5147750b6890205397e2 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 4/7] Get rid of blivet.blivet's dependence on
 blivet.osinstall.FSSet

All of the FSSet stuff pertains to installation, so move everything
from Blivet to InstallerStorageConfig subclass. The methods and
properties moved are:
    file_system_free_space
    root_device (prop)
    update_ksdata
    _update_custom_storage_ksdata
These now only exist in InstallerStorageConfig.

This also creates the "mountpoints" property in blivet.devicetree

This property fits pretty nicely in conjunction with other properties
living inside of the devicetree. It also simplifies things in
blivet.osinstall.FSSet.
---
 blivet/blivet.py     | 176 ++++-----------------------------------------------
 blivet/devicetree.py |   9 +++
 blivet/osinstall.py  | 175 ++++++++++++++++++++++++++++++++++++++++++++++++--
 3 files changed, 190 insertions(+), 170 deletions(-)

diff --git a/blivet/blivet.py b/blivet/blivet.py
index 9de73d7..a3b7407 100644
--- a/blivet/blivet.py
+++ b/blivet/blivet.py
@@ -28,10 +28,10 @@ import time
 import parted
 import functools
 
-from pykickstart.constants import AUTOPART_TYPE_LVM, CLEARPART_TYPE_ALL, CLEARPART_TYPE_LIST, CLEARPART_TYPE_NONE
+from pykickstart.constants import AUTOPART_TYPE_LVM
 
 from .storage_log import log_method_call, log_exception_info
-from .devices import BTRFSDevice, BTRFSSubVolumeDevice, BTRFSVolumeDevice
+from .devices import BTRFSSubVolumeDevice, BTRFSVolumeDevice
 from .devices import LVMLogicalVolumeDevice, LVMVolumeGroupDevice
 from .devices import MDRaidArrayDevice, PartitionDevice, TmpFSDevice, device_path_to_name
 from .deviceaction import ActionCreateDevice, ActionCreateFormat, ActionDestroyDevice
@@ -46,7 +46,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 FSSet, StorageDiscoveryConfig find_existing_installations
+from .osinstall import StorageDiscoveryConfig find_existing_installations
 from . import arch
 from .iscsi import iscsi
 from .fcoe import fcoe
@@ -55,8 +55,6 @@ from . import devicefactory
 from . import get_bootloader, get_sysroot, short_product_name, __version__
 from .threads import SynchronizedMeta
 
-from .i18n import _
-
 import logging
 log = logging.getLogger("blivet")
 
@@ -106,7 +104,6 @@ class Blivet(object, metaclass=SynchronizedMeta):
                                      ignored_disks=self.ignored_disks,
                                      exclusive_disks=self.exclusive_disks,
                                      disk_images=self.disk_images)
-        self.fsset = FSSet(self.devicetree)
         self.roots = []
         self.services = set()
         self._free_space_snapshot = None
@@ -231,7 +228,6 @@ class Blivet(object, metaclass=SynchronizedMeta):
                               exclusive_disks=self.exclusive_disks,
                               disk_images=self.disk_images)
         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:
@@ -1101,32 +1097,6 @@ class Blivet(object, metaclass=SynchronizedMeta):
         self.devicetree.set_disk_images(self.disk_images)
         self.devicetree.setup_disk_images()
 
-    @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 dump_state(self, suffix):
         """ Dump the current device list to the storage shelf. """
         key = "devices.%d.%s" % (time.time(), suffix)
@@ -1153,7 +1123,6 @@ class Blivet(object, metaclass=SynchronizedMeta):
         if not os.path.isdir("%s/etc" % get_sysroot()):
             os.mkdir("%s/etc" % get_sysroot())
 
-        self.fsset.write()
         iscsi.write(get_sysroot(), self)
         fcoe.write(get_sysroot())
         zfcp.write(get_sysroot())
@@ -1174,6 +1143,14 @@ class Blivet(object, metaclass=SynchronizedMeta):
                 f.write("%s\n" % " ".join(fields),)
 
     @property
+    def boot_device(self):
+        dev = None
+        root_device = self.mountpoints.get("/")
+
+        dev = self.mountpoints.get("/boot", root_device)
+        return dev
+
+    @property
     def bootloader(self):
         if self._bootloader is None and flags.installer_mode:
             self._bootloader = get_bootloader()
@@ -1223,13 +1200,6 @@ class Blivet(object, metaclass=SynchronizedMeta):
         return disk
 
     @property
-    def boot_device(self):
-        dev = None
-        if self.fsset:
-            dev = self.mountpoints.get("/boot", self.root_device)
-        return dev
-
-    @property
     def bootloader_device(self):
         return getattr(self.bootloader, "stage1_device", None)
 
@@ -1294,11 +1264,7 @@ class Blivet(object, metaclass=SynchronizedMeta):
 
     @property
     def mountpoints(self):
-        return self.fsset.mountpoints
-
-    @property
-    def root_device(self):
-        return self.fsset.root_device
+        return self.devicetree.mountpoints
 
     def compare_disks(self, first, second):
         if not isinstance(first, str):
@@ -1460,124 +1426,6 @@ class Blivet(object, metaclass=SynchronizedMeta):
         log.debug("finished Blivet copy")
         return new
 
-    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)
-
     @property
     def free_space_snapshot(self):
         # if no snapshot is available, do it now and return it
diff --git a/blivet/devicetree.py b/blivet/devicetree.py
index edfa0bb..d10d36d 100644
--- a/blivet/devicetree.py
+++ b/blivet/devicetree.py
@@ -778,6 +778,15 @@ class DeviceTreeBase(object, metaclass=SynchronizedMeta):
 
         return labels
 
+    @property
+    def mountpoints(self):
+        """ Dict with mountpoint keys and Device values. """
+        filesystems = {}
+        for device in self.devices:
+            if device.format.mountable and device.format.mountpoint:
+                filesystems[device.format.mountpoint] = device
+        return filesystems
+
     #
     # Disk filter
     #
diff --git a/blivet/osinstall.py b/blivet/osinstall.py
index d6ab6f1..75f67c4 100644
--- a/blivet/osinstall.py
+++ b/blivet/osinstall.py
@@ -38,13 +38,16 @@ from . import get_sysroot, get_target_physical_root, error_handler, ERROR_RAISE
 
 from .blivet import Blivet
 from .storage_log import log_exception_info
-from .devices import FileDevice, NFSDevice, NoDevice, OpticalDevice, NetworkStorageDevice, DirectoryDevice, MDRaidArrayDevice, PartitionDevice
+from .devices import FileDevice, NFSDevice, NoDevice, OpticalDevice, NetworkStorageDevice, DirectoryDevice
+from .devices import PartitionDevice, BTRFSSubVolumeDevice, TmpFSDevice, LVMLogicalVolumeDevice, LVMVolumeGroupDevice
+from .devices import MDRaidArrayDevice, BTRFSDevice
 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 .platform import platform as _platform
 from .platform import EFI
+from .size import Size
 
 from .i18n import _
 
@@ -402,11 +405,7 @@ class FSSet(object):
 
     @property
     def mountpoints(self):
-        filesystems = {}
-        for device in self.devices:
-            if device.format.mountable and device.format.mountpoint:
-                filesystems[device.format.mountpoint] = device
-        return filesystems
+        return self.devicetree.mountpoints
 
     def _parse_one_line(self, devspec, mountpoint, fstype, options, _dump="0", _passno="0"):
         """Parse an fstab entry for a device, return the corresponding device.
@@ -1246,6 +1245,170 @@ class InstallerStorageConfig(Blivet):
         zfcp.write(get_sysroot())
 
     @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.fsset = FSSet(self.devicetree)
+
+    def reset(self, cleanup_only=False):
+        Blivet.reset(self, cleanup_only)
+
+        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:
-- 
2.7.4

