From a8e6ff5aa841f9415d5c3ba4d12526f22ee86130 Mon Sep 17 00:00:00 2001
From: David Lehman <dlehman@redhat.com>
Date: Mon, 14 Jan 2013 12:36:22 -0600
Subject: [PATCH 07/11] Start laying groundwork for splitting storage out of
 pyanaconda.

Remove platform's use of bootloader in preparation for moving platform
into storage, since that's the only code that uses it.

Move some logging initialization code in network.py into a function so
it does not run automatically on import.

Add some code to storage to control whether or not it is being used by
anaconda versus as a normal python module/library.
---
 anaconda                           |    6 ++++
 pyanaconda/__init__.py             |   10 ++++---
 pyanaconda/anaconda_log.py         |    5 ++-
 pyanaconda/bootloader.py           |   22 ++++++++++++++-
 pyanaconda/iutil.py                |    3 +-
 pyanaconda/network.py              |   27 ++++++++++--------
 pyanaconda/platform.py             |   12 --------
 pyanaconda/storage/__init__.py     |   52 ++++++++++++++++++++++++++++-------
 pyanaconda/storage/dasd.py         |    2 +-
 pyanaconda/storage/deviceaction.py |   14 +++++++---
 pyanaconda/storage/fcoe.py         |   10 +++---
 pyanaconda/storage/iscsi.py        |    2 +-
 pyanaconda/storage/zfcp.py         |    2 +-
 13 files changed, 112 insertions(+), 55 deletions(-)

diff --git a/anaconda b/anaconda
index ca4961d..2bfd7ab 100755
--- a/anaconda
+++ b/anaconda
@@ -658,6 +658,9 @@ if __name__ == "__main__":
     anaconda_log.init()
     anaconda_log.logger.setupVirtio()
 
+    from pyanaconda import network
+    network.setup_ifcfg_log()
+
     log = logging.getLogger("anaconda")
     stdoutLog = logging.getLogger("anaconda.stdout")
 
@@ -927,6 +930,9 @@ if __name__ == "__main__":
     from pyanaconda.threads import initThreading, threadMgr, AnacondaThread
     initThreading()
 
+    from pyanaconda import storage
+    storage.enable_installer_mode()
+
     # now start the interface
     setupDisplay(anaconda, opts, addon_paths)
 
diff --git a/pyanaconda/__init__.py b/pyanaconda/__init__.py
index b217547..0b8119b 100644
--- a/pyanaconda/__init__.py
+++ b/pyanaconda/__init__.py
@@ -30,11 +30,11 @@
 
 import os, time, string
 import sys
-from pyanaconda.storage import arch
-import isys
 from constants import ROOT_PATH
 from tempfile import mkstemp
 
+from pyanaconda.bootloader import get_bootloader
+
 import logging
 log = logging.getLogger("anaconda")
 stdoutLog = logging.getLogger("anaconda.stdout")
@@ -71,7 +71,9 @@ class Anaconda(object):
         self.rescue = False
         self.rescue_mount = True
         self.rootParts = None
-        self.simpleFilter = not arch.isS390()
+
+        # use os.uname because it's too early to be importing storage
+        self.simpleFilter = not os.uname()[4].startswith('s390')
         self.stage2 = None
         self._storage = None
         self.updateSrc = None
@@ -85,7 +87,7 @@ class Anaconda(object):
     @property
     def bootloader(self):
         if not self._bootloader:
-            self._bootloader = self.platform.bootloaderClass(self.platform)
+            self._bootloader = get_bootloader(self.platform)
 
         return self._bootloader
 
diff --git a/pyanaconda/anaconda_log.py b/pyanaconda/anaconda_log.py
index 4391927..36c79f0 100644
--- a/pyanaconda/anaconda_log.py
+++ b/pyanaconda/anaconda_log.py
@@ -30,7 +30,6 @@ import sys
 import types
 import warnings
 
-from pyanaconda.storage import arch
 from flags import flags
 
 DEFAULT_TTY_LEVEL = logging.INFO
@@ -105,7 +104,9 @@ class AnacondaLog:
             logger.setLevel(logging.DEBUG)
             self.forwardToSyslog(logger)
             # Logging of basic stuff and storage to tty3.
-            if not arch.isS390() and os.access(MAIN_LOG_TTY, os.W_OK):
+            # XXX Use os.uname here since it's too early to be importing the
+            #     storage module.
+            if not os.uname()[4].startswith('s390') and os.access(MAIN_LOG_TTY, os.W_OK):
                 self.addFileHandler(MAIN_LOG_TTY, logger,
                                     fmtStr=TTY_FORMAT,
                                     autoLevel=True)
diff --git a/pyanaconda/bootloader.py b/pyanaconda/bootloader.py
index 6ea7477..b3a60ff 100644
--- a/pyanaconda/bootloader.py
+++ b/pyanaconda/bootloader.py
@@ -36,6 +36,7 @@ from pyanaconda.constants import *
 from pyanaconda.storage.errors import StorageError
 from pyanaconda.storage.fcoe import fcoe
 import pyanaconda.network
+from pyanaconda import platform as _platform
 
 import gettext
 _ = lambda x: gettext.ldgettext("anaconda", x)
@@ -44,7 +45,6 @@ N_ = lambda x: x
 import logging
 log = logging.getLogger("storage")
 
-
 def get_boot_block(device, seek_blocks=0):
     status = device.status
     if not status:
@@ -2191,6 +2191,26 @@ class UBOOT(BootLoader):
         if rc:
             raise BootLoaderError("bootloader install failed")
 
+
+# every platform that wants a bootloader needs to be in this dict
+bootloader_by_platform = {_platform.X86: GRUB2,
+                          _platform.EFI: EFIGRUB,
+                          _platform.MacEFI: MacEFIGRUB,
+                          _platform.PPC: GRUB2,
+                          _platform.IPSeriesPPC: IPSeriesGRUB2,
+                          _platform.NewWorldPPC: MacYaboot,
+                          _platform.S390: ZIPL,
+                          _platform.Sparc: SILO,
+                          _platform.ARM: UBOOT,
+                          _platform.omapARM: UBOOT}
+
+def get_bootloader(platform):
+    platform_name = platform.__class__.__name__
+    cls = bootloader_by_platform.get(platform.__class__, BootLoader)
+    log.info("bootloader %s on %s platform" % (cls.__name__, platform_name))
+    return cls(platform)
+
+
 # anaconda-specific functions
 
 def writeSysconfigKernel(storage, version):
diff --git a/pyanaconda/iutil.py b/pyanaconda/iutil.py
index 66024c5..dbc7c3b 100644
--- a/pyanaconda/iutil.py
+++ b/pyanaconda/iutil.py
@@ -183,7 +183,8 @@ def mkdirChain(dir):
 
 def isConsoleOnVirtualTerminal():
     # XXX PJFIX is there some way to ask the kernel this instead?
-    if isS390():
+    # XXX we don't want to have to import storage from here
+    if os.uname()[4].startswith("s390"):
         return False
     return not flags.serial
 
diff --git a/pyanaconda/network.py b/pyanaconda/network.py
index f968fba..1f2bf19 100644
--- a/pyanaconda/network.py
+++ b/pyanaconda/network.py
@@ -61,19 +61,22 @@ DEFAULT_HOSTNAME = "localhost.localdomain"
 # for more info about '(?!-)' and '(?<!-)' see 're' module documentation
 HOSTNAME_PART_RE = re.compile("(?!-)[A-Z\d-]{1,63}(?<!-)$", re.IGNORECASE)
 
-# Setup special logging for ifcfg NM interface
-from pyanaconda import anaconda_log
-logger = logging.getLogger("ifcfg")
-logger.setLevel(logging.DEBUG)
-anaconda_log.logger.addFileHandler(ifcfgLogFile, logger, logging.DEBUG)
-if os.access("/dev/tty3", os.W_OK):
-    anaconda_log.logger.addFileHandler("/dev/tty3", logger,
-                                       anaconda_log.DEFAULT_TTY_LEVEL,
-                                       anaconda_log.TTY_FORMAT,
-                                       autoLevel=True)
-anaconda_log.logger.forwardToSyslog(logger)
-
-ifcfglog = logging.getLogger("ifcfg")
+ifcfglog = None
+def setup_ifcfg_log():
+    # Setup special logging for ifcfg NM interface
+    from pyanaconda import anaconda_log
+    global ifcfglog
+    logger = logging.getLogger("ifcfg")
+    logger.setLevel(logging.DEBUG)
+    anaconda_log.logger.addFileHandler(ifcfgLogFile, logger, logging.DEBUG)
+    if os.access("/dev/tty3", os.W_OK):
+        anaconda_log.logger.addFileHandler("/dev/tty3", logger,
+                                           anaconda_log.DEFAULT_TTY_LEVEL,
+                                           anaconda_log.TTY_FORMAT,
+                                           autoLevel=True)
+    anaconda_log.logger.forwardToSyslog(logger)
+
+    ifcfglog = logging.getLogger("ifcfg")
 
 class IPError(Exception):
     pass
diff --git a/pyanaconda/platform.py b/pyanaconda/platform.py
index 2012cdb..39b49ec 100644
--- a/pyanaconda/platform.py
+++ b/pyanaconda/platform.py
@@ -25,7 +25,6 @@ log = logging.getLogger("anaconda")
 
 import parted
 
-from pyanaconda import bootloader
 from pyanaconda.storage import arch
 
 from flags import flags
@@ -44,7 +43,6 @@ class Platform(object):
     _minimumSector = 0
     _packages = []
 
-    bootloaderClass = bootloader.BootLoader
     # requirements for bootloader stage1 devices
     _boot_stage1_device_types = []
     _boot_stage1_format_types = []
@@ -151,7 +149,6 @@ class Platform(object):
             return 0
 
 class X86(Platform):
-    bootloaderClass = bootloader.GRUB2
     _boot_stage1_device_types = ["disk"]
     _boot_mbr_description = N_("Master Boot Record")
     _boot_descriptions = {"disk": _boot_mbr_description,
@@ -184,7 +181,6 @@ class X86(Platform):
             return 0
 
 class EFI(Platform):
-    bootloaderClass = bootloader.EFIGRUB
 
     _boot_stage1_format_types = ["efi"]
     _boot_stage1_device_types = ["partition"]
@@ -215,8 +211,6 @@ class EFI(Platform):
             return 0
 
 class MacEFI(EFI):
-    bootloaderClass = bootloader.MacEFIGRUB
-
     _boot_stage1_format_types = ["hfs+"]
     _boot_efi_description = N_("Apple EFI Boot Partition")
     _non_linux_format_types = ["hfs+"]
@@ -232,7 +226,6 @@ class MacEFI(EFI):
 
 class PPC(Platform):
     _ppcMachine = arch.getPPCMachine()
-    bootloaderClass = bootloader.GRUB2
     _boot_stage1_device_types = ["partition"]
 
     @property
@@ -240,7 +233,6 @@ class PPC(Platform):
         return self._ppcMachine
 
 class IPSeriesPPC(PPC):
-    bootloaderClass = bootloader.IPSeriesGRUB2
     _boot_stage1_format_types = ["prepboot"]
     _boot_stage1_max_end_mb = 10
     _boot_prep_description = N_("PReP Boot Partition")
@@ -264,7 +256,6 @@ class IPSeriesPPC(PPC):
             return 0
 
 class NewWorldPPC(PPC):
-    bootloaderClass = bootloader.MacYaboot
     _boot_stage1_format_types = ["appleboot"]
     _boot_apple_description = N_("Apple Bootstrap Partition")
     _boot_descriptions = {"partition": _boot_apple_description}
@@ -291,7 +282,6 @@ class PS3(PPC):
     pass
 
 class S390(Platform):
-    bootloaderClass = bootloader.ZIPL
     _packages = ["s390utils"]
     _disklabel_types = ["msdos", "dasd"]
     _boot_stage1_device_types = ["disk", "partition"]
@@ -319,7 +309,6 @@ class S390(Platform):
         return super(S390, self).requiredDiskLabelType(device_type)
 
 class Sparc(Platform):
-    bootloaderClass = bootloader.SILO
     _boot_stage1_format_types = []
     _boot_stage1_mountpoints = []
     _boot_stage1_max_end_mb = None
@@ -334,7 +323,6 @@ class Sparc(Platform):
 
 class ARM(Platform):
     _armMachine = None
-    bootloaderClass = bootloader.UBOOT
     _boot_stage1_device_types = ["disk"]
     _boot_mbr_description = N_("Master Boot Record")
     _boot_descriptions = {"disk": _boot_mbr_description,
diff --git a/pyanaconda/storage/__init__.py b/pyanaconda/storage/__init__.py
index 94f6263..f6cd380 100644
--- a/pyanaconda/storage/__init__.py
+++ b/pyanaconda/storage/__init__.py
@@ -20,6 +20,15 @@
 # Red Hat Author(s): Dave Lehman <dlehman@redhat.com>
 #
 
+##
+## Default stub values for installer-specific stuff that gets set up in
+## enable_installer_mode.
+##
+isys = None
+ROOT_PATH = '/'
+shortProductName = ''
+bootLoaderError = Exception
+
 import os
 import time
 import stat
@@ -31,11 +40,8 @@ import copy
 import nss.nss
 import parted
 
-from pyanaconda.constants import *
 from pykickstart.constants import *
 from pyanaconda import tsort
-from pyanaconda.errors import *
-from pyanaconda.bootloader import BootLoaderError
 
 from storage_log import log_method_call
 from errors import *
@@ -62,12 +68,7 @@ import zfcp
 import dasd
 import util
 import arch
-import flags
-
-if flags.installer_mode:
-    from pyanaconda import isys
-else:
-    isys = None
+from flags import flags
 
 import shelve
 import contextlib
@@ -78,6 +79,21 @@ _ = lambda x: gettext.ldgettext("anaconda", x)
 import logging
 log = logging.getLogger("storage")
 
+def enable_installer_mode():
+    global isys
+    global ROOT_PATH
+    global shortProductName
+    global get_bootloader
+    global BootLoaderError
+
+    from pyanaconda import isys
+    from pyanaconda.constants import ROOT_PATH
+    from pyanaconda.constants import shortProductName
+    from pyanaconda.bootloader import get_bootloader
+    from pyanaconda.bootloader import BootLoaderError
+
+    flags.installer_mode = True
+
 DEVICE_TYPE_LVM = 0
 DEVICE_TYPE_MD = 1
 DEVICE_TYPE_PARTITION = 2
@@ -120,6 +136,9 @@ def getRAIDLevel(device):
     return raid_level
 
 def storageInitialize(storage, ksdata, protected):
+    from pyanaconda.flags import flags as anaconda_flags
+    flags.update_from_anaconda_flags(anaconda_flags)
+
     storage.shutdown()
 
     # touch /dev/.in_sysinit so that /lib/udev/rules.d/65-md-incremental.rules
@@ -155,6 +174,9 @@ def storageInitialize(storage, ksdata, protected):
             log.debug("onlyuse is now: %s" % (",".join(ksdata.ignoredisk.onlyuse)))
 
 def turnOnFilesystems(storage):
+    if not flags.installer_mode:
+        return
+
     if (flags.live_install and not flags.image_install and not storage.fsset.active):
         # turn off any swaps that we didn't turn on
         # needed for live installs
@@ -1669,8 +1691,10 @@ class Storage(object):
 
     @property
     def bootloader(self):
-        if self._bootloader is None and self.platform is not None:
-            self._bootloader = self.platform.bootloaderClass(self.platform)
+        if self._bootloader is None and self.platform is not None and \
+           flags.installer_mode:
+            self._bootloader = get_bootloader(self.platform)
+
         return self._bootloader
 
     def updateBootLoaderDiskList(self):
@@ -2801,6 +2825,9 @@ class FSSet(object):
 
     def turnOnSwap(self, rootPath="", upgrading=None):
         """ Activate the system's swap space. """
+        if not flags.installer_mode:
+            return
+
         for device in self.swapDevices:
             if isinstance(device, FileDevice):
                 # set up FileDevices' parents now that they are accessible
@@ -2828,6 +2855,9 @@ class FSSet(object):
     def mountFilesystems(self, rootPath="", readOnly=None,
                          skipRoot=False, raiseErrors=None):
         """ Mount the system's filesystems. """
+        if not flags.installer_mode:
+            return
+
         devices = self.mountpoints.values() + self.swapDevices
         devices.extend([self.dev, self.devshm, self.devpts, self.sysfs,
                         self.proc, self.selinux, self.usb])
diff --git a/pyanaconda/storage/dasd.py b/pyanaconda/storage/dasd.py
index 752ca05..abf97b9 100644
--- a/pyanaconda/storage/dasd.py
+++ b/pyanaconda/storage/dasd.py
@@ -25,7 +25,7 @@ from pyanaconda.storage.errors import DasdFormatError
 from pyanaconda.storage.devices import deviceNameToDiskByPath
 from pyanaconda.storage import util
 from pyanaconda.storage import arch
-from pyanaconda.constants import *
+from . import ROOT_PATH
 from pyanaconda.baseudev import udev_trigger
 
 import logging
diff --git a/pyanaconda/storage/deviceaction.py b/pyanaconda/storage/deviceaction.py
index 7cb17c4..c8f96f2 100644
--- a/pyanaconda/storage/deviceaction.py
+++ b/pyanaconda/storage/deviceaction.py
@@ -37,6 +37,16 @@ _ = lambda x: gettext.ldgettext("anaconda", x)
 import logging
 log = logging.getLogger("storage")
 
+from contextlib import contextmanager
+
+@contextmanager
+def progress_report_stub(message):
+    yield
+
+try:
+    from pyanaconda.progress import progress_report
+except ImportError:
+    progress_report = progress_report_stub
 
 # The values are just hints as to the ordering.
 # Eg: fsmod and devmod ordering depends on the mod (shrink -v- grow)
@@ -405,8 +415,6 @@ class ActionCreateFormat(DeviceAction):
             self.origFormat = getFormat(None)
 
     def execute(self):
-        from pyanaconda.progress import progress_report
-
         msg = _("Creating %(type)s on %(device)s") % {"type": self.device.format.type, "device": self.device.path}
         with progress_report(msg):
             self.device.setup()
@@ -545,8 +553,6 @@ class ActionResizeFormat(DeviceAction):
         self.device.format.targetSize = newsize
 
     def execute(self):
-        from pyanaconda.progress import progress_report
-
         msg = _("Resizing filesystem on %(device)s") % {"device": self.device.path}
         with progress_report(msg):
             self.device.setup(orig=True)
diff --git a/pyanaconda/storage/fcoe.py b/pyanaconda/storage/fcoe.py
index 3a4d147..22c6258 100644
--- a/pyanaconda/storage/fcoe.py
+++ b/pyanaconda/storage/fcoe.py
@@ -20,8 +20,8 @@
 import os
 from . import util
 from pyanaconda.baseudev import udev_settle
-from pyanaconda import isys
-from pyanaconda.constants import ROOT_PATH
+#from pyanaconda import isys
+from . import ROOT_PATH
 import logging
 import time
 log = logging.getLogger("storage")
@@ -76,9 +76,9 @@ class fcoe(object):
             return
 
         (key, val) = rc.strip().split("=", 1)
-        if val not in isys.getDeviceProperties():
-            log.error("Unknown FCoE NIC found in EDD: %s, ignoring" % val)
-            return
+        #if val not in isys.getDeviceProperties():
+        #    log.error("Unknown FCoE NIC found in EDD: %s, ignoring" % val)
+        #    return
 
         log.info("FCoE NIC found in EDD: %s" % val)
         self.addSan(val, dcb=True, auto_vlan=True)
diff --git a/pyanaconda/storage/iscsi.py b/pyanaconda/storage/iscsi.py
index 4e64335..8b7cbf8 100644
--- a/pyanaconda/storage/iscsi.py
+++ b/pyanaconda/storage/iscsi.py
@@ -18,7 +18,7 @@
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #
 
-from pyanaconda.constants import *
+from . import ROOT_PATH
 from udev import udev_settle
 from . import util
 from .flags import flags
diff --git a/pyanaconda/storage/zfcp.py b/pyanaconda/storage/zfcp.py
index 27dd107..23be6cd 100644
--- a/pyanaconda/storage/zfcp.py
+++ b/pyanaconda/storage/zfcp.py
@@ -21,7 +21,7 @@
 
 import string
 import os
-from pyanaconda.constants import *
+from . import ROOT_PATH
 from udev import udev_settle
 from . import util
 
-- 
1.7.6.5

