[rhel7/master] Check for ready before baseRepo in completed (#1044985)
by Brian C. Lane
From: "Brian C. Lane" <bcl(a)redhat.com>
The completed spoke method can be called before the spoke has finished
initializing itself in cases where the spoke launches its initialize
method in a thread. This can lead to attributes being accessed before
they are ready (namely yum related items).
This adds a check for self.ready to the source and software completed
methods and re-orders the checks so that ready will short out access to
problem attributes like baseRepo.
It also adds some warning docstrings so we don't forget why this can
be a problem.
Resolves: rhbz#1044985
---
pyanaconda/ui/common.py | 4 ++++
pyanaconda/ui/gui/spokes/__init__.py | 4 ++++
pyanaconda/ui/gui/spokes/source.py | 5 ++++-
pyanaconda/ui/tui/spokes/software.py | 12 ++++++++----
pyanaconda/ui/tui/spokes/source.py | 2 +-
5 files changed, 21 insertions(+), 6 deletions(-)
diff --git a/pyanaconda/ui/common.py b/pyanaconda/ui/common.py
index 6fc51ae..f73f3d2 100644
--- a/pyanaconda/ui/common.py
+++ b/pyanaconda/ui/common.py
@@ -282,6 +282,10 @@ class Spoke(UIObject):
spoke, and a highlighted message will be shown at the bottom of the
Hub. Installation will not be allowed to proceed until all mandatory
spokes are complete.
+
+ WARNING: This can be called before the spoke is finished initializing
+ if the spoke starts a thread. It should make sure it doesn't access
+ things until they are completely setup.
"""
return False
diff --git a/pyanaconda/ui/gui/spokes/__init__.py b/pyanaconda/ui/gui/spokes/__init__.py
index c1a35b3..3581668 100644
--- a/pyanaconda/ui/gui/spokes/__init__.py
+++ b/pyanaconda/ui/gui/spokes/__init__.py
@@ -43,6 +43,10 @@ class Spoke(GUIObject):
icon will be shown on the Hub beside the spoke, and a highlighted
message will be shown at the bottom of the Hub. Installation will not
be allowed to proceed until all spokes are complete.
+
+ WARNING: This can be called before the spoke is finished initializing
+ if the spoke starts a thread. It should make sure it doesn't access
+ things until they are completely setup.
"""
return False
diff --git a/pyanaconda/ui/gui/spokes/source.py b/pyanaconda/ui/gui/spokes/source.py
index 67aeab3..431acf1 100644
--- a/pyanaconda/ui/gui/spokes/source.py
+++ b/pyanaconda/ui/gui/spokes/source.py
@@ -485,7 +485,10 @@ class SourceSpoke(NormalSpoke):
@property
def completed(self):
- if flags.automatedInstall and (not self.data.method.method or not self.payload.baseRepo):
+ """ WARNING: This can be called before _initialize is done, make sure that it
+ doesn't access things that are not setup (eg. payload.*) until it is ready
+ """
+ if flags.automatedInstall and self.ready and (not self.data.method.method or not self.payload.baseRepo):
return False
else:
return not self._error and self.ready and (self.data.method.method or self.payload.baseRepo)
diff --git a/pyanaconda/ui/tui/spokes/software.py b/pyanaconda/ui/tui/spokes/software.py
index 3c88445..e1ecfae 100644
--- a/pyanaconda/ui/tui/spokes/software.py
+++ b/pyanaconda/ui/tui/spokes/software.py
@@ -103,14 +103,18 @@ class SoftwareSpoke(NormalTUISpoke):
@property
def completed(self):
- """ Make sure our threads are done running and vars are set. """
- processingDone = not threadMgr.get(THREAD_CHECK_SOFTWARE) and \
- not self.errors and self.txid_valid
+ """ Make sure our threads are done running and vars are set.
+
+ WARNING: This can be called before the spoke is finished initializing
+ if the spoke starts a thread. It should make sure it doesn't access
+ things until they are completely setup.
+ """
+ processingDone = self.ready and not self.errors and self.txid_valid
if flags.automatedInstall:
return processingDone and self.payload.baseRepo and self.data.packages.seen
else:
- return self.payload.baseRepo and self.environment is not None and processingDone
+ return processingDone and self.payload.baseRepo and self.environment is not None
def refresh(self, args=None):
""" Refresh screen. """
diff --git a/pyanaconda/ui/tui/spokes/source.py b/pyanaconda/ui/tui/spokes/source.py
index b1aed2d..aefdb0f 100644
--- a/pyanaconda/ui/tui/spokes/source.py
+++ b/pyanaconda/ui/tui/spokes/source.py
@@ -221,7 +221,7 @@ class SourceSpoke(SourceSwitchHandler, EditTUISpoke):
@property
def completed(self):
- if flags.automatedInstall and (not self.data.method.method or not self.payload.baseRepo):
+ if flags.automatedInstall and self.ready and (not self.data.method.method or not self.payload.baseRepo):
return False
else:
return not self.errors and self.ready and (self.data.method.method or self.payload.baseRepo)
--
1.8.3.1
10 years, 4 months
[master/rhel7-branch] Display additional disk attributes in TUI storage spoke. (#1024760)
by Samantha N. Bueno
Note: I've only tested this with normal disks and s390x-specific
devices (DASD, zFCP). I might try and test this with some other
specialized device configurations to make sure information looks all
right and does not break anything, but I think it should be ok.
For DASDs, for instance, this is what is now shown:
Install Destination
[ ] 1) IBM S390 DASD drive: 2.34 GB (dasda), 0.0.0200
[ ] 2) IBM S390 DASD drive: 2.34 GB (dasdb), 0.0.0201
[ ] 3) IBM S390 DASD drive: 2.34 GB (dasdc), 0.0.0202
[ ] 4) IBM S390 DASD drive: 2.34 GB (dasdd), 0.0.0203
====
Some specialized disks are difficult to identify by name and model
alone in the TUI storage spoke, so show additional disk attributes
to help distinguish among devices.
Resolves: rhbz#1024760
---
pyanaconda/ui/tui/spokes/storage.py | 33 ++++++++++++++++++++++++++++++---
1 file changed, 30 insertions(+), 3 deletions(-)
diff --git a/pyanaconda/ui/tui/spokes/storage.py b/pyanaconda/ui/tui/spokes/storage.py
index 00fa9fe..de68813 100644
--- a/pyanaconda/ui/tui/spokes/storage.py
+++ b/pyanaconda/ui/tui/spokes/storage.py
@@ -29,6 +29,7 @@ from pyanaconda.ui.tui.simpleline import TextWidget, CheckboxWidget
from pykickstart.constants import AUTOPART_TYPE_LVM, AUTOPART_TYPE_BTRFS, AUTOPART_TYPE_PLAIN
from blivet.size import Size
from blivet.errors import StorageError
+from blivet.devices import DASDDevice, FcoeDiskDevice, iScsiDiskDevice, MultipathDevice, ZFCPDiskDevice
from pyanaconda.flags import flags
from pyanaconda.kickstart import doKickstartStorage
from pyanaconda.threads import threadMgr, AnacondaThread
@@ -182,9 +183,8 @@ class StorageSpoke(NormalTUISpoke):
# loop through the disks and present them.
for disk in self.disks:
- size = size_str(disk.size)
- c = CheckboxWidget(title="%i) %s: %s (%s)" % (self.disks.index(disk) + 1,
- disk.model, size, disk.name),
+ disk_info = self._format_disk_info(disk)
+ c = CheckboxWidget(title="%i) %s" % (self.disks.index(disk) + 1, disk_info),
completed=(disk.name in self.selected_disks))
self._window += [c, ""]
@@ -192,6 +192,33 @@ class StorageSpoke(NormalTUISpoke):
return True
+ def _format_disk_info(self, disk):
+ """ Some specialized disks are difficult to identify in the storage
+ spoke, so add and return extra identifying information about them.
+
+ Since this is going to be ugly to do within the confines of the
+ CheckboxWidget, pre-format the display string here.
+ """
+ # show this info for all disks
+ format_str = "%s: %s (%s)" % (disk.model, size_str(disk.size), disk.name)
+
+ disk_attrs = []
+ # now check for/add info about special disks
+ if (isinstance(disk, MultipathDevice) or isinstance(disk, iScsiDiskDevice) or isinstance(disk, FcoeDiskDevice)):
+ disk_attrs.append(disk.wwid)
+ elif isinstance(disk, DASDDevice):
+ disk_attrs.append(disk.busid)
+ elif isinstance (disk, ZFCPDiskDevice):
+ disk_attrs.append(disk.fcp_lun)
+ disk_attrs.append(disk.wwpn)
+ disk_attrs.append(disk.hba_id)
+
+ # now append all additional attributes to our string
+ for attr in disk_attrs:
+ format_str += ", %s" % attr
+
+ return format_str
+
def input(self, args, key):
"""Grab the disk choice and update things"""
--
1.8.3.1
10 years, 4 months
[master][PATCH] Fix 'select all disks' logic in TUI storage spoke.
by Samantha N. Bueno
If a user chose 'select all disks', the selected/unselected flag would
just get flipped for each device, even if it had already been selected
manually. This changes the logic to only toggle 'selected' if a disk is
not already present in selected_disks.
---
pyanaconda/ui/tui/spokes/storage.py | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/pyanaconda/ui/tui/spokes/storage.py b/pyanaconda/ui/tui/spokes/storage.py
index 6567fca..bd04c99 100644
--- a/pyanaconda/ui/tui/spokes/storage.py
+++ b/pyanaconda/ui/tui/spokes/storage.py
@@ -209,8 +209,9 @@ class StorageSpoke(NormalTUISpoke):
def _select_all_disks(self):
""" Mark all disks as selected for use in partitioning. """
- for i in self.disks:
- self._update_disk_list(i)
+ for disk in self.disks:
+ if disk.name not in self.selected_disks:
+ self._update_disk_list(disk)
def input(self, args, key):
"""Grab the disk choice and update things"""
--
1.8.3.1
10 years, 4 months
[master/rhel7-branch] Fix vncpasswd handling
by David Shea
Fedora bug 1045119, cloned to 1045162 for RHEL
In order to log program output, our iutil exec functions split the output based
on python's universal newline detection, which isn't so great when we have
binary data that contains \r or \n. Added some options to fix that and used the
options with vncpasswd.
10 years, 4 months
[blivet] Don't translate format names
by David Shea
Until we get a better answer for whether or not this even makes sense,
leave format names untranslated to avoid problems with all the code that
expects untranslated format names.
---
blivet/formats/__init__.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/blivet/formats/__init__.py b/blivet/formats/__init__.py
index 5e0ea32..a0e6767 100644
--- a/blivet/formats/__init__.py
+++ b/blivet/formats/__init__.py
@@ -251,7 +251,7 @@ class DeviceFormat(object):
@property
def name(self):
if self._name:
- name = _(self._name)
+ name = self._name
else:
name = self.type
return name
--
1.8.4.2
10 years, 4 months
[rhel7-branch/master] Print a message and exit if a user attempts to upgrade via kickstart.
by David Shea
The expected behavior from the upgrade command is different enough from
what would actually happen that we should terminate the installation
instead of simply ignoring it as deprecated.
Resolves: rhbz#1036756
(Obviously the version on master should say "fedup" and not "redhat-upgrade-tool")
---
pyanaconda/kickstart.py | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/pyanaconda/kickstart.py b/pyanaconda/kickstart.py
index c79acd3..d9deb4f 100644
--- a/pyanaconda/kickstart.py
+++ b/pyanaconda/kickstart.py
@@ -1484,6 +1484,14 @@ class Keyboard(commands.keyboard.F18_Keyboard):
def dracutSetupArgs(self, *args):
return keyboard.dracut_setup_args(self)
+class Upgrade(commands.upgrade.F20_Upgrade):
+ # Upgrade is no longer supported. If an upgrade command was included in
+ # a kickstart, warn the user and exit.
+ # pylint: disable-msg=W0231
+ def __init__(self, *args):
+ log.error("The upgrade kickstart command is no longer supported. Upgrade functionality is provided through redhat-upgrade-tool.")
+ sys.stderr.write(_("The upgrade kickstart command is no longer supported. Upgrade functionality is provided through redhat-upgrade-tool."))
+ sys.exit(1)
class SpokeRegistry(dict):
"""This class represents the ksdata.firstboot object and
@@ -1545,6 +1553,7 @@ commandMap = {
"selinux": SELinux,
"services": Services,
"timezone": Timezone,
+ "upgrade": Upgrade,
"user": User,
"volgroup": VolGroup,
"xconfig": XConfig,
--
1.8.4.2
10 years, 4 months
[rhel7-branch] Don't show the language twice for keyboard layouts
by David Shea
Adapted from 291e12cb0233905e413f34d5289c73a7df1d19a7. Many layout
descriptions include the layout name, so there's no need to add the
language again in that case.
Resolves: rhbz#1021849
---
pyanaconda/keyboard.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/pyanaconda/keyboard.py b/pyanaconda/keyboard.py
index 81b1388..c8e1924 100755
--- a/pyanaconda/keyboard.py
+++ b/pyanaconda/keyboard.py
@@ -465,7 +465,7 @@ class XklWrapper(object):
#if this layout has already been added for some other language,
#do not add it again (would result in duplicates in our lists)
if name not in self.name_to_show_str:
- if lang:
+ if lang and not description.startswith(lang):
self.name_to_show_str[name] = "%s (%s)" % (lang.encode("utf-8"),
description.encode("utf-8"))
else:
--
1.8.4.2
10 years, 4 months
[blivet:rhel7/master 0/4] Guard against bad filesystem labels
by Anne Mulhern
These changes are all brought about by rhbz#1038590
The problem there is that the format of a filesystem label is unacceptable
to the application that is used to set it.
The idea is to catch the problem when the format is initialized instead
of when the label is set.
This will also require some changes to anaconda, to catch the exception
thrown by the _setLabel method when calling, e.g., getFormat.
I haven't done that yet, I'm seeking a review on the blivet side first.
mulhern (4):
Add some simple tests for file formats.
Changes to _getLabelArgs and fields on which it depends (#1038590)
Change FS.label to a property (#1038590)
Remove label parameter from writeLabel method (#1038590)
blivet/formats/fs.py | 101 +++++++++++++++++++++++++++++-----------
tests/formats_test/__init__.py | 0
tests/formats_test/misc_test.py | 97 ++++++++++++++++++++++++++++++++++++++
3 files changed, 172 insertions(+), 26 deletions(-)
create mode 100644 tests/formats_test/__init__.py
create mode 100755 tests/formats_test/misc_test.py
--
1.8.3.1
10 years, 4 months
[rhel6-branch] Copy firmware updates to rootPath (#1043372)
by Brian C. Lane
From: "Brian C. Lane" <bcl(a)redhat.com>
This moves copytree from livecd to iutil so that copyFirmware can use it
to copy the whole DD_FIRMWARE tree over to /lib/firmware/
Resolves: rhbz#1043372
---
backend.py | 16 +++++++++-------
iutil.py | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
livecd.py | 64 +-------------------------------------------------------------
3 files changed, 72 insertions(+), 70 deletions(-)
diff --git a/backend.py b/backend.py
index 55ebff4..7b73c71 100644
--- a/backend.py
+++ b/backend.py
@@ -72,13 +72,15 @@ class AnacondaBackend:
self.initLog(anaconda.id, anaconda.rootPath)
def copyFirmware(self, anaconda):
- # Multiple driver disks may be loaded, so we need to glob for all
- # the firmware files in the common DD firmware directory
- for f in glob.glob(DD_FIRMWARE+"/*"):
- try:
- shutil.copyfile(f, "%s/lib/firmware/" % anaconda.rootPath)
- except IOError, e:
- log.error("Could not copy firmware file %s: %s" % (f, e.strerror))
+ if not os.path.isdir(DD_FIRMWARE):
+ return
+
+ # Multiple driver disks may be loaded, and there may also be
+ # firmware updates, so recursively copy the firmware directory over
+ try:
+ iutil.copytree(DD_FIRMWARE, anaconda.rootPath+"/lib/firmware/")
+ except iutil.Error, e:
+ log.errors("Error copying %s: %s" % (DD_FIRMWARE, e.strerror))
def doPostInstall(self, anaconda):
diff --git a/iutil.py b/iutil.py
index f837f7a..53473df 100644
--- a/iutil.py
+++ b/iutil.py
@@ -32,6 +32,7 @@ from flags import flags
from constants import *
import re
import threading
+import selinux
import gettext
_ = lambda x: gettext.ldgettext("anaconda", x)
@@ -991,3 +992,64 @@ def lsmod():
with open("/proc/modules") as f:
lines = f.readlines()
return [l.split()[0] for l in lines]
+
+class Error(EnvironmentError):
+ pass
+
+def copytree(src, dst, symlinks=False, preserveOwner=False,
+ preserveSelinux=False):
+ def tryChown(src, dest):
+ try:
+ os.chown(dest, os.stat(src)[stat.ST_UID], os.stat(src)[stat.ST_GID])
+ except OverflowError:
+ log.error("Could not set owner and group on file %s" % dest)
+
+ def trySetfilecon(src, dest):
+ try:
+ selinux.lsetfilecon(dest, selinux.lgetfilecon(src)[1])
+ except:
+ log.error("Could not set selinux context on file %s" % dest)
+
+ # copy of shutil.copytree which doesn't require dst to not exist
+ # and which also has options to preserve the owner and selinux contexts
+ names = os.listdir(src)
+ if not os.path.isdir(dst):
+ os.makedirs(dst)
+ errors = []
+ for name in names:
+ srcname = os.path.join(src, name)
+ dstname = os.path.join(dst, name)
+ try:
+ if symlinks and os.path.islink(srcname):
+ linkto = os.readlink(srcname)
+ os.symlink(linkto, dstname)
+ if preserveSelinux:
+ trySetfilecon(srcname, dstname)
+ elif os.path.isdir(srcname):
+ copytree(srcname, dstname, symlinks, preserveOwner, preserveSelinux)
+ else:
+ shutil.copyfile(srcname, dstname)
+ if preserveOwner:
+ tryChown(srcname, dstname)
+
+ if preserveSelinux:
+ trySetfilecon(srcname, dstname)
+
+ shutil.copystat(srcname, dstname)
+ except (IOError, os.error), why:
+ errors.append((srcname, dstname, str(why)))
+ # catch the Error from the recursive copytree so that we can
+ # continue with other files
+ except Error, err:
+ errors.extend(err.args[0])
+ try:
+ if preserveOwner:
+ tryChown(src, dst)
+ if preserveSelinux:
+ trySetfilecon(src, dst)
+
+ shutil.copystat(src, dst)
+ except OSError as e:
+ errors.extend((src, dst, e.strerror))
+ if errors:
+ raise Error, errors
diff --git a/livecd.py b/livecd.py
index fd1ff48..340bcce 100644
--- a/livecd.py
+++ b/livecd.py
@@ -31,8 +31,6 @@ import time
import subprocess
import storage
-import selinux
-
from flags import flags
from constants import *
@@ -48,66 +46,6 @@ import packages
import logging
log = logging.getLogger("anaconda")
-class Error(EnvironmentError):
- pass
-def copytree(src, dst, symlinks=False, preserveOwner=False,
- preserveSelinux=False):
- def tryChown(src, dest):
- try:
- os.chown(dest, os.stat(src)[stat.ST_UID], os.stat(src)[stat.ST_GID])
- except OverflowError:
- log.error("Could not set owner and group on file %s" % dest)
-
- def trySetfilecon(src, dest):
- try:
- selinux.lsetfilecon(dest, selinux.lgetfilecon(src)[1])
- except:
- log.error("Could not set selinux context on file %s" % dest)
-
- # copy of shutil.copytree which doesn't require dst to not exist
- # and which also has options to preserve the owner and selinux contexts
- names = os.listdir(src)
- if not os.path.isdir(dst):
- os.makedirs(dst)
- errors = []
- for name in names:
- srcname = os.path.join(src, name)
- dstname = os.path.join(dst, name)
- try:
- if symlinks and os.path.islink(srcname):
- linkto = os.readlink(srcname)
- os.symlink(linkto, dstname)
- if preserveSelinux:
- trySetfilecon(srcname, dstname)
- elif os.path.isdir(srcname):
- copytree(srcname, dstname, symlinks, preserveOwner, preserveSelinux)
- else:
- shutil.copyfile(srcname, dstname)
- if preserveOwner:
- tryChown(srcname, dstname)
-
- if preserveSelinux:
- trySetfilecon(srcname, dstname)
-
- shutil.copystat(srcname, dstname)
- except (IOError, os.error), why:
- errors.append((srcname, dstname, str(why)))
- # catch the Error from the recursive copytree so that we can
- # continue with other files
- except Error, err:
- errors.extend(err.args[0])
- try:
- if preserveOwner:
- tryChown(src, dst)
- if preserveSelinux:
- trySetfilecon(src, dst)
-
- shutil.copystat(src, dst)
- except OSError as e:
- errors.extend((src, dst, e.strerror))
- if errors:
- raise Error, errors
-
class LiveCDCopyBackend(backend.AnacondaBackend):
def __init__(self, anaconda):
backend.AnacondaBackend.__init__(self, anaconda)
@@ -304,7 +242,7 @@ class LiveCDCopyBackend(backend.AnacondaBackend):
# nothing to move
continue
- copytree("%s/%s" % (anaconda.rootPath, tocopy),
+ iutil.copytree("%s/%s" % (anaconda.rootPath, tocopy),
"%s/mnt/%s" % (anaconda.rootPath, tocopy),
True, True, flags.selinux)
wait.refresh()
--
1.8.3.1
10 years, 4 months
[PATCH rhel7-branch] Fix a typo (#1039223)
by Radek Vykydal
Related: rhbz#1039223
---
pyanaconda/kickstart.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/pyanaconda/kickstart.py b/pyanaconda/kickstart.py
index cb04bc2..9cb9f58 100644
--- a/pyanaconda/kickstart.py
+++ b/pyanaconda/kickstart.py
@@ -529,7 +529,7 @@ class Fcoe(commands.fcoe.F13_Fcoe):
msg = blivet.fcoe.fcoe().addSan(nic=fc.nic, dcb=fc.dcb, auto_vlan=True) or "Succeeded."
- log.info("adding FCoE SAN on %s: %s", (fc.nic, msg))
+ log.info("adding FCoE SAN on %s: %s" % (fc.nic, msg))
return fc
--
1.7.11.7
10 years, 4 months