Add support for installing onto block device image files.
Multiple image files can be specified via "--image=/path/to/image[:name]"
on the anaconda command line. The name cannot contain colons.
Whenever disk images are specified, they automatically become the
only disks visible to anaconda, as if "ignoredisks --only-use" had
been used.
Fow now, only normal disk images are supported. Do not try to build
a fwraid or mpath in image files and expect anaconda to handle it
correctly.
Don't log to system log for disk image installs. For one thing, it adds
a huge amount of text to /var/log/messages. It also has some problem
that prevents subsequent attempts to connect to the syslog socket (from
anaconda_log.py, anyway) to fail.
Don't allow configuration of network devices during disk image installs.
Also, don't write anything in /etc/sysconfig on the host system
when doing image installs.
Don't start auditd when doing an image install.
Don't run setupTimezone if installing to disk image file(s). We don't
want to change settings on the host system.
# Deprecated, unloved, unused
op.add_option("-r", "--rootPath", dest="unsupportedMode",
@@ -471,6 +472,12 @@ if __name__ == "__main__":
# this handles setting up updates for pypackages to minimize the set needed
setupPythonUpdates()
+ # do this early so we can set flags before initializing logging
+ (opts, args) = parseOptions()
+ from pyanaconda.flags import flags
+ if opts.images:
+ flags.imageInstall = True
+
# Set up logging as early as possible.
import logging
from pyanaconda import anaconda_log
@@ -498,8 +505,6 @@ if __name__ == "__main__":
from pyanaconda import kickstart
import pyanaconda.storage.storage_log
- from pyanaconda.flags import flags
-
# the following makes me very sad. -- katzj
# we have a slightly different set of udev rules in the second
# stage than the first stage. why this doesn't get picked up
@@ -538,7 +543,6 @@ if __name__ == "__main__":
vncS = vnc.VncServer() # The vnc Server object.
vncS.anaconda = anaconda
# check memory, just the text mode for now:
@@ -606,6 +610,23 @@ if __name__ == "__main__":
(path, name) = string.split(mod, ":")
anaconda.extraModules.append((path, name))
+ image_count = 0
+ for image in opts.images:
+ image_spec = image.rsplit(":", 1)
+ path = image_spec[0]
+ if len(image_spec) == 2 and image_spec[1].strip():
+ name = image_spec[1].strip()
+ else:
+ name = os.path.splitext(os.path.basename(path))[0]
+
+ if "/" in name or name in anaconda.storage.config.diskImages.keys():
+ name = "diskimg%d" % image_count
+
+ log.info("naming disk image '%s' '%s'" % (path, name))
+ anaconda.storage.config.diskImages[name] = path
+ image_count += 1
+ flags.imageInstall = True
+
if opts.vnc:
flags.usevnc = 1
anaconda.displayMode = 'g'
@@ -642,7 +663,7 @@ if __name__ == "__main__":
anaconda.xdriver = opts.xdriver
anaconda.writeXdriver(root="/")
- if not flags.livecdInstall:
+ if not flags.livecdInstall and not flags.imageInstall:
startAuditDaemon()
# setup links required for all install types
diff --git a/anaconda.spec.in b/anaconda.spec.in
index e1a7efa..2b19f9a 100644
--- a/anaconda.spec.in
+++ b/anaconda.spec.in
@@ -216,6 +216,7 @@ update-desktop-database &> /dev/null || :
%{_libdir}/python*/site-packages/pyanaconda/*
%{_libdir}/python*/site-packages/log_picker/*
%{_libdir}/anaconda*
+%{_bindir}/anaconda-image-cleanup
%ifarch %livearches
%{_bindir}/liveinst
%{_sbindir}/liveinst
diff --git a/data/liveinst/liveinst b/data/liveinst/liveinst
index e424a62..46213a8 100755
--- a/data/liveinst/liveinst
+++ b/data/liveinst/liveinst
@@ -18,6 +18,30 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
+if [ -n "$DISPLAY" -a -n "$LANG" ]; then
+ INSTLANG="--lang $LANG"
+fi
+
+LIVE_INSTALL=0
+IMAGE_INSTALL=0
+RESCUE=0
+if [[ "$LIVECMD $*" =~ "--rescue" ]]; then
+ RESCUE=1
+fi
+
+if [ -z "$LIVECMD" ]; then
+ LIVE_INSTALL=1
+fi
+
+if [[ "$LIVECMD $*" =~ "--image" ]]; then
+ IMAGE_INSTALL=1
+fi
+
+if [[ "$LIVECMD $*" =~ "--liveinst" ]]; then
+ LIVE_INSTALL=1
+fi
+
+
if [ -z "$LIVE_BLOCK" ]; then
if [ -b "/dev/mapper/live-osimg-min" ]; then
LIVE_BLOCK="/dev/mapper/live-osimg-min"
@@ -26,16 +50,25 @@ if [ -z "$LIVE_BLOCK" ]; then
fi
fi
-if [ ! -b $LIVE_BLOCK ]; then
+if [ $LIVE_INSTALL = 1 -a ! -b $LIVE_BLOCK ]; then
zenity --error --title="Not a Live image" --text "Can't do live image installation unless running from a live image"
exit 1
fi
+# Allow running another command in the place of anaconda, but in this same
+# environment. This allows storage testing to make use of all the module
+# loading and lvm control in this file, too.
+ANACONDA=${LIVECMD:=/usr/sbin/anaconda --liveinst --method=livecd://$LIVE_BLOCK $INSTLANG}
+
# load modules that would get loaded by the loader... (#230945)
for i in raid0 raid1 raid5 raid6 raid456 raid10 dm-mod dm-zero dm-mirror dm-snapshot dm-multipath dm-round-robin vfat dm-crypt cbc sha256 lrw xts iscsi_tcp iscsi_ibft; do /sbin/modprobe $i 2>/dev/null ; done
RELEASE=$(rpm -q --qf '%{Release}' fedora-release)
@@ -47,15 +80,6 @@ fi
export PATH=/sbin:/usr/sbin:$PATH
-if [ -n "$DISPLAY" -a -n "$LANG" ]; then
- INSTLANG="--lang $LANG"
-fi
-
-# Allow running another command in the place of anaconda, but in this same
-# environment. This allows storage testing to make use of all the module
-# loading and lvm control in this file, too.
-ANACONDA=${LIVECMD:=/usr/sbin/anaconda --liveinst --method=livecd://$LIVE_BLOCK $INSTLANG}
-
if [ -x /usr/sbin/setenforce -a -e /selinux/enforce ]; then
current=$(cat /selinux/enforce)
/usr/sbin/setenforce 0
@@ -74,34 +98,38 @@ for opt in `cat /proc/cmdline`; do
esac
done
-# devkit-disks is now mounting lots of stuff. for now, let's just try to unmount it all
-umount /media/* 2>/dev/null
-tac /proc/mounts | grep ^/dev | grep -v live | while read dev mntpoint rest; do
- # hack - don't unmount devices the storage test code requires
- if [ "$mntpoint" = "/mnt/anactest" ]; then
- continue
- fi
-
- if [ -b $dev ]; then
- umount $mntpoint 2>/dev/null
- fi
-done
-
-/sbin/swapoff -a
-/sbin/lvm vgchange -an --ignorelockingfailure
-for i in /dev/md*; do
- if [ ! -b $i ]; then
- continue
- fi
-
- case "$i" in
- /dev/md*p*)
- ;;
- *)
- mdadm --stop $i >/dev/null 2>&1
- ;;
- esac
-done
+if [ $IMAGE_INSTALL = 0 ]; then
+ # devkit-disks is now mounting lots of stuff. for now, let's just try to
+ # unmount it all
+ umount /media/* 2>/dev/null
+ tac /proc/mounts | grep ^/dev | grep -v live |
+ while read dev mntpoint rest; do
+ # hack - don't unmount devices the storage test code requires
+ if [ "$mntpoint" = "/mnt/anactest" ]; then
+ continue
+ fi
+
+ if [ -b $dev ]; then
+ umount $mntpoint 2>/dev/null
+ fi
+ done
+
+ /sbin/swapoff -a
+ /sbin/lvm vgchange -an --ignorelockingfailure
+ for i in /dev/md*; do
+ if [ ! -b $i ]; then
+ continue
+ fi
+
+ case "$i" in
+ /dev/md*p*)
+ ;;
+ *)
+ mdadm --stop $i >/dev/null 2>&1
+ ;;
+ esac
+ done
+fi
/sbin/udevadm control --env=ANACONDA=1
@@ -113,6 +141,13 @@ else
$ANACONDA $*
fi
+# try to teardown the filesystems if this was an image install
+if [ $IMAGE_INSTALL = 1 -a $RESCUE = 0 ]; then
+ anaconda-image-cleanup
+fi
+
+rm -f /dev/.in_sysinit 2>/dev/null
+
if [ -n "$current" ]; then
/usr/sbin/setenforce $current
fi
diff --git a/pyanaconda/anaconda_log.py b/pyanaconda/anaconda_log.py
index 2f48630..c298b4e 100644
--- a/pyanaconda/anaconda_log.py
+++ b/pyanaconda/anaconda_log.py
@@ -30,6 +30,7 @@ from logging.handlers import SysLogHandler, SYSLOG_UDP_PORT
import types
import iutil
+from flags import flags
DEFAULT_TTY_LEVEL = logging.INFO
ENTRY_FORMAT = "%(asctime)s,%(msecs)03d %(levelname)s %(name)s: %(message)s"
@@ -129,6 +130,10 @@ class AnacondaLog:
def forwardToSyslog(self, logger):
"""Forward everything that goes in the logger to the syslog daemon.
"""
+ if flags.imageInstall:
+ # don't clutter up the system logs when doing an image install
+ return
+
syslogHandler = AnacondaSyslogHandler(
'/dev/log',
ANACONDA_SYSLOG_FACILITY,
diff --git a/pyanaconda/flags.py b/pyanaconda/flags.py
index 79a5e66..68a53b1 100644
--- a/pyanaconda/flags.py
+++ b/pyanaconda/flags.py
@@ -93,6 +93,7 @@ class Flags:
self.__dict__['flags']['sshd'] = 0
self.__dict__['flags']['preexisting_x11'] = False
self.__dict__['flags']['noverifyssl'] = False
+ self.__dict__['flags']['imageInstall'] = False
# for non-physical consoles like some ppc and sgi altix,
# we need to preserve the console device and not try to
# do things like bogl on them. this preserves what that
diff --git a/pyanaconda/iw/congrats_gui.py b/pyanaconda/iw/congrats_gui.py
index c80f2f8..e5a3af3 100644
--- a/pyanaconda/iw/congrats_gui.py
+++ b/pyanaconda/iw/congrats_gui.py
@@ -22,6 +22,7 @@ import gtk
from pyanaconda import gui
from iw_gui import *
from pyanaconda.constants import *
+from pyanaconda.flags import flags
import os
from pyanaconda import platform
@@ -45,7 +46,7 @@ class CongratulationWindow (InstallWindow):
# this mucks around a bit, but it's the weird case and it's
# better than adding a lot of complication to the normal
ics.cw.mainxml.get_widget("nextButton").hide()
- if os.path.exists(os.environ.get("LIVE_BLOCK", "/dev/mapper/live-osimg-min")):
+ if flags.livecdInstall or flags.imageInstall:
ics.cw.mainxml.get_widget("closeButton").show()
ics.cw.mainxml.get_widget("closeButton").grab_focu s()
else:
diff --git a/pyanaconda/iw/network_gui.py b/pyanaconda/iw/network_gui.py
index 9f7c40d..4f1ec17 100644
--- a/pyanaconda/iw/network_gui.py
+++ b/pyanaconda/iw/network_gui.py
@@ -26,6 +26,7 @@ from iw_gui import *
from pyanaconda import gui
from pyanaconda import network
from pyanaconda import iutil
+from pyanaconda.flags import flags
import gobject
import subprocess
import gtk
@@ -50,7 +51,7 @@ class NetworkWindow(InstallWindow):
self.netconfButton = self.xml.get_widget("netconfButton")
self.netconfButton.connect("clicked", self._setupNetwork)
- if len(self.anaconda.network.netdevices) == 0:
+ if len(self.anaconda.network.netdevices) == 0 or flags.imageInstall:
self.netconfButton.set_sensitive(False)
# pressing Enter in confirm == clicking Next
diff --git a/pyanaconda/network.py b/pyanaconda/network.py
index 8b567d5..9cad759 100644
--- a/pyanaconda/network.py
+++ b/pyanaconda/network.py
@@ -356,12 +356,14 @@ class Network:
self.setNMControlledDevices(self.netdevices.keys() )
+ if flags.imageInstall:
+ return
+
# populate self.netdevices
devhash = isys.getDeviceProperties(dev=None)
for iface in devhash.keys():
@@ -643,6 +645,14 @@ class Network:
return True
def copyConfigToPath(self, instPath='):
+ if flags.imageInstall and instPath:
+ # for image installs we only want to write out
+ # /etc/sysconfig/network
+ destfile = os.path.normpath(instPath + networkConfFile)
+ if not os.path.isdir(os.path.dirname(destfile)):
+ iutil.mkdirChain(os.path.dirname(destfile))
+ shutil.move("/tmp/sysconfig-network", destfile)
+ return
- devices = self.netdevices.values()
-
- # /etc/sysconfig/network-scripts/ifcfg-*
- # /etc/sysconfig/network-scripts/keys-*
- for dev in devices:
-
- bootproto = dev.get('BOOTPROTO').lower()
- # write out the hostname as DHCP_HOSTNAME if given (#81613)
- if (bootproto == 'dhcp' and self.hostname and
- self.overrideDHCPhostname):
- dev.set(('DHCP_HOSTNAME', self.hostname))
-
- dev.writeIfcfgFile()
-
- if dev.wepkey:
- dev.writeWepkeyFile(dir=netscriptsDir, overwrite=False)
-
-
# /etc/sysconfig/network
- newnetwork = "%s.new" % (networkConfFile)
+ if flags.imageInstall:
+ # don't write files into host's /etc/sysconfig on image installs
+ newnetwork = "/tmp/sysconfig-network"
+ else:
+ newnetwork = "%s.new" % (networkConfFile)
f = open(newnetwork, "w")
f.write("NETWORKING=yes
")
@@ -723,7 +718,30 @@ class Network:
f.write("IPV6_DEFAULTGW=%s
" % self.ipv6_defaultgw)
f.close()
- shutil.move(newnetwork, networkConfFile)
+ if flags.imageInstall:
+ # for image installs, all we want to write out is the contents of
+ # /etc/sysconfig/network
+ ifcfglog.debug("not writing per-device configs for image install")
+ return
+ else:
+ shutil.move(newnetwork, networkConfFile)
+
+ devices = self.netdevices.values()
+
+ # /etc/sysconfig/network-scripts/ifcfg-*
+ # /etc/sysconfig/network-scripts/keys-*
+ for dev in devices:
+
+ bootproto = dev.get('BOOTPROTO').lower()
+ # write out the hostname as DHCP_HOSTNAME if given (#81613)
+ if (bootproto == 'dhcp' and self.hostname and
+ self.overrideDHCPhostname):
+ dev.set(('DHCP_HOSTNAME', self.hostname))
+
+ dev.writeIfcfgFile()
+
+ if dev.wepkey:
+ dev.writeWepkeyFile(dir=netscriptsDir, overwrite=False)
def setupTimezone(anaconda):
# we don't need this on an upgrade or going backwards
- if anaconda.upgrade or anaconda.dir == DISPATCH_BACK:
+ if anaconda.upgrade or flags.imageInstall or anaconda.dir == DISPATCH_BACK:
return
# make sure they have a resolv.conf in the chroot
def makeResolvConf(instPath):
+ if flags.imageInstall:
+ return
+
if not os.access("/etc/resolv.conf", os.R_OK):
return
@@ -218,8 +221,13 @@ def runShell(screen = None, msg=""):
print
if msg:
print (msg)
- print(_("When finished please exit from the shell and your "
- "system will reboot."))
+
+ if flags.imageInstall:
+ print(_("Run anaconda-image-cleanup to unmount the system "
+ "when you are finished."))
+ else:
+ print(_("When finished please exit from the shell and your "
+ "system will reboot."))
print
+ if not flags.imageInstall:
+ msg = _("The system will reboot automatically when you exit "
+ "from the shell.")
+ else:
+ msg = _("Run anaconda-image-cleanup to unmount the system "
+ "when you are finished.")
+
if rc == -1:
if anaconda.ksdata:
log.error("System had dirty file systems which you chose not to mount")
@@ -374,9 +389,8 @@ def runRescue(anaconda):
ButtonChoiceWindow(screen, _("Rescue"),
_("Your system had dirty file systems which you chose not "
"to mount. Press return to get a shell from which "
- "you can fsck and mount your partitions. The system "
- "will reboot automatically when you exit from the "
- "shell."), [_("OK")], width = 50)
+ "you can fsck and mount your partitions. %s") % msg,
+ [_("OK")], width = 50)
rootmounted = 0
else:
if anaconda.ksdata:
@@ -386,9 +400,9 @@ def runRescue(anaconda):
_("Your system has been mounted under %(rootPath)s.
"
"Press <return> to get a shell. If you would like to "
"make your system the root environment, run the command:
"
- " chroot %(rootPath)s
The system will reboot "
- "automatically when you exit from the shell.") %
- {'rootPath': anaconda.rootPath},
+ " chroot %(rootPath)s
# set a library path to use mounted fs
- libdirs = os.environ["LD_LIBRARY_PATH"].split(":")
+ libdirs = os.environ.get("LD_LIBRARY_PATH", "").split(":")
mounted = map(lambda dir: "/mnt/sysimage%s" % dir, libdirs)
os.environ["LD_LIBRARY_PATH"] = ":".join(libdirs + mounted)
@@ -467,11 +481,18 @@ def runRescue(anaconda):
if anaconda.ksdata:
log.error("An error occurred trying to mount some or all of your system")
else:
+ if not flags.imageInstall:
+ msg = _("The system will reboot automatically when you "
+ "exit from the shell.")
+ else:
+ msg = _("Run anaconda-image-cleanup to unmount the system "
+ "when you are finished.")
+
ButtonChoiceWindow(screen, _("Rescue"),
_("An error occurred trying to mount some or all of your "
"system. Some of it may be mounted under %s.
"
- "Press <return> to get a shell. The system will reboot "
- "automatically when you exit from the shell.") % (anaconda.rootPath,),
+ "Press <return> to get a shell. %s")
+ % (anaconda.rootPath, msg),
[_("OK")] )
else:
if anaconda.ksdata and
@@ -481,10 +502,14 @@ def runRescue(anaconda):
print(_("You don't have any Linux partitions. Rebooting.
"))
sys.exit(0)
else:
+ if not flags.imageInstall:
+ msg = _(" The system will reboot automatically when you exit "
+ "from the shell.")
+ else:
+ msg = ""
ButtonChoiceWindow(screen, _("Rescue Mode"),
_("You don't have any Linux partitions. Press "
- "return to get a shell. The system will reboot "
- "automatically when you exit from the shell."),
+ "return to get a shell.%s") % msg,
[ _("OK") ], width = 50)
if msg:
raise LoopError("failed to set up loop for %s: %s" % (path, msg))
@@ -91,7 +91,7 @@ def loop_teardown(path):
try:
msg = losetup(args)
except LoopError as e:
- msg = e.message
+ msg = str(e)
if msg:
raise DeviceError("failed to tear down loop %s: %s" % (path, msg))
diff --git a/pyanaconda/storage/devices.py b/pyanaconda/storage/devices.py
index dc4d930..85bfa1e 100644
--- a/pyanaconda/storage/devices.py
+++ b/pyanaconda/storage/devices.py
@@ -1686,7 +1686,7 @@ class DMLinearDevice(DMDevice):
# information about it
self._size = self.currentSize
- def deactivate(self):
+ def deactivate(self, recursive=False):
if not self.exists:
raise DeviceError("device has not been created", self.name)
@@ -1702,6 +1702,9 @@ class DMLinearDevice(DMDevice):
dm.dm_remove(self.name)
udev_settle()
+ if recursive:
+ self.teardownParents(recursive=recursive)
+
def teardown(self, recursive=None):
""" Close, or tear down, a device. """
log_method_call(self, self.name, status=self.status)
diff --git a/pyanaconda/storage/devicetree.py b/pyanaconda/storage/devicetree.py
index 81cbc96..2981d35 100644
--- a/pyanaconda/storage/devicetree.py
+++ b/pyanaconda/storage/devicetree.py
@@ -24,6 +24,7 @@ import os
import stat
import block
import re
+import shutil
from errors import *
from devices import *
@@ -35,6 +36,7 @@ import devicelibs.mdraid
import devicelibs.dm
import devicelibs.lvm
import devicelibs.mpath
+import devicelibs.loop
from udev import *
from .storage_log import log_method_call
from pyanaconda import iutil
@@ -170,6 +172,11 @@ class DeviceTree(object):
self.iscsi = iscsi
self.dasd = dasd
+ # disk image files are automatically exclusive
+ self.diskImages = getattr(conf, "diskImages", {})
+ if self.diskImages:
+ self.exclusiveDisks = self.diskImages.keys()
+
# protected device specs as provided by the user
self.protectedDevSpecs = getattr(conf, "protectedDevSpecs", [])
@@ -527,6 +534,11 @@ class DeviceTree(object):
self.exclusiveDisks[i] = name
return False
+ # never ignore mapped disk images. if you don't want to use them,
+ # don't specify them in the first place
+ if udev_device_is_dm_anaconda(info):
+ return False
+
# We want exclusiveDisks to operate on anything that could be
# considered a directly usable disk, ie: fwraid array, mpath, or disk.
#
@@ -548,9 +560,14 @@ class DeviceTree(object):
# udev.py: enumerate_block_devices(), but we can still end up trying
# to add them to the tree when they are slaves of other devices, this
# happens for example with the livecd
- if name.startswith("loop") or name.startswith("ram"):
+ if name.startswith("ram"):
return True
+ if name.startswith("loop"):
+ # ignore loop devices unless they're backed by a disk image file
+ backing_device = devicelibs.loop.get_device_path(name)
+ return (backing_device not in self.diskImages.values())
+
# FIXME: check for virtual devices whose slaves are on the ignore list
def addUdevDMDevice(self, info):
@@ -1521,11 +1538,99 @@ class DeviceTree(object):
return ret
+ def setupDiskImages(self):
+ for (name, path) in self.diskImages.items():
+ log.info("setting up disk image file '%s' as '%s'" % (path, name))
+ try:
+ filedev = FileDevice(path, exists=True)
+ filedev.setup()
+ log.debug("%s" % filedev)
+
+ loop_name = devicelibs.loop.get_loop_name(filedev.path)
+ loop_sysfs = None
+ if loop_name:
+ loop_sysfs = "/class/block/%s" % loop_name
+ loopdev = LoopDevice(name=loop_name,
+ parents=[filedev],
+ sysfsPath=loop_sysfs,
+ exists=True)
+ loopdev.setup()
+ log.debug("%s" % loopdev)
+ dmdev = DMLinearDevice(name,
+ parents=[loopdev],
+ exists=True)
+ dmdev.setup()
+ dmdev.updateSysfsPath()
+ log.debug("%s" % dmdev)
+ except (ValueError, DeviceError) as e:
+ log.error("failed to set up disk image: %s" % e)
+ else:
+ self._addDevice(filedev)
+ self._addDevice(loopdev)
+ self._addDevice(dmdev)
+ info = udev_get_block_device(dmdev.sysfsPath)
+ self.addUdevDevice(info)
+
+ def backupConfigs(self, restore=False):
+ """ Create a backup copies of some storage config files. """
+ configs = ["/etc/mdadm.conf", "/etc/multipath.conf"]
+ for cfg in configs:
+ if restore:
+ src = cfg + ".anacbak"
+ dst = cfg
+ func = os.rename
+ op = "restore from backup"
+ else:
+ src = cfg
+ dst = cfg + ".anacbak"
+ func = shutil.copy2
+ op = "create backup copy"
+
+ if os.access(dst, os.W_OK):
+ try:
+ os.unlink(dst)
+ except OSError as e:
+ msg = str(e)
+ log.info("failed to remove %s: %s" % (dst, msg))
+
+ if os.access(src, os.W_OK):
+ # copy the config to a backup with extension ".anacbak"
+ try:
+ func(src, dst)
+ except (IOError, OSError) as e:
+ msg = str(e)
+ log.error("failed to %s of %s: %s" % (op, cfg, msg))
+ elif restore:
+ # remove the config since we created it
+ log.info("removing anaconda-created %s" % cfg)
+ try:
+ os.unlink(cfg)
+ except OSError as e:
+ msg = str(e)
+ log.error("failed to remove %s: %s" % (cfg, msg))
+ else:
+ # don't try to backup non-existent configs
+ log.info("not going to %s of non-existent %s" % (op, cfg))
+
+ def restoreConfigs(self):
+ self.backupConfigs(restore=True)
+
def populate(self):
""" Locate all storage devices. """
+ self.backupConfigs()
+ try:
+ self._populate()
+ except Exception:
+ raise
+ finally:
+ self.restoreConfigs()
+
+ def _populate(self):
log.debug("DeviceTree.populate: ignoredDisks is %s ; exclusiveDisks is %s"
% (self._ignoredDisks, self.exclusiveDisks))
+ self.setupDiskImages()
+
# mark the tree as unpopulated so exception handlers can tell the
# exception originated while finding storage devices
self.populated = False
@@ -1622,10 +1727,6 @@ class DeviceTree(object):
self._handleInconsistencies()
def teardownAll(self):
""" Run teardown methods on all devices. """
diff --git a/pyanaconda/storage/udev.py b/pyanaconda/storage/udev.py
index 1f4c3d5..9dfe37c 100644
--- a/pyanaconda/storage/udev.py
+++ b/pyanaconda/storage/udev.py
@@ -107,7 +107,7 @@ def udev_get_block_devices():
def __is_blacklisted_blockdev(dev_name):
"""Is this a blockdev we never want for an install?"""
- if dev_name.startswith("loop") or dev_name.startswith("ram") or dev_name.startswith("fd"):
+ if dev_name.startswith("ram") or dev_name.startswith("fd"):
return True
if os.path.exists("/sys/class/block/%s/device/model" %(dev_name,)):
diff --git a/scripts/Makefile.am b/scripts/Makefile.am
index 187d4c6..839567d 100644
--- a/scripts/Makefile.am
+++ b/scripts/Makefile.am
@@ -28,6 +28,8 @@ dist_noinst_SCRIPTS = getlangnames.py upd-bootimage upd-initrd upd-kernel
analogdir = $(libexecdir)/$(PACKAGE_NAME)
dist_analog_SCRIPTS = analog
I suppose if I were picky enough, I could find something to change. But
for now, I'm happy with this one going in and we can deal with any minor
bugs as they come up.
- Chris
_______________________________________________
Anaconda-devel-list mailing list
Anaconda-devel-list@redhat.com
https://www.redhat.com/mailman/listinfo/anaconda-devel-list