[PATCH] network gui: do not crash on devices without settings (eg wireless) (#1010519)
by Radek Vykydal
Also do not read slaves from settings but use new 'Slaves' property to read
current slaves instead.
---
pyanaconda/network.py | 21 +++++++++------------
pyanaconda/nm.py | 23 +++++++++++++++++++++++
2 files changed, 32 insertions(+), 12 deletions(-)
diff --git a/pyanaconda/network.py b/pyanaconda/network.py
index dcb6ee0..18ea892 100644
--- a/pyanaconda/network.py
+++ b/pyanaconda/network.py
@@ -34,6 +34,7 @@ import threading
import re
import dbus
import IPy
+import itertools
from simpleconfig import SimpleConfigFile
from blivet.devices import FcoeDiskDevice, iScsiDiskDevice
@@ -1046,22 +1047,16 @@ def status_message():
slaves = {}
ssids = {}
- nonslaves = []
# first find slaves and wireless aps
for devname in active_devs:
- master = nm.nm_device_setting_value(devname, "connection", "master")
- if master:
- if master in slaves:
- slaves[master].append(devname)
- else:
- slaves[master] = [devname]
- else:
- nonslaves.append(devname)
+ slaves[devname] = nm.nm_device_slaves(devname) or []
if nm.nm_device_type_is_wifi(devname):
ssids[devname] = nm.nm_device_active_ssid(devname) or ""
- if len(nonslaves) == 1:
+ all_slaves = set(itertools.chain.from_iterable(slaves.values()))
+
+ if len(active_devs) - len(all_slaves) == 1:
if nm.nm_device_type_is_ethernet(devname):
msg = _("Wired (%(interface_name)s) connected") \
% {"interface_name": devname}
@@ -1077,9 +1072,11 @@ def status_message():
vlanid = nm.nm_device_setting_value(devname, "vlan", "id")
msg = _("Vlan %(interface_name)s (%(parent_device)s, ID %(vlanid)s) connected") \
% {"interface_name": devname, "parent_device": parent, "vlanid": vlanid}
- elif len(nonslaves) > 1:
+ elif len(active_devs) - len(all_slaves) > 1:
devlist = []
- for devname in nonslaves:
+ for devname in active_devs:
+ if devname in all_slaves:
+ continue
if nm.nm_device_type_is_ethernet(devname):
devlist.append("%s" % devname)
elif nm.nm_device_type_is_wifi(devname):
diff --git a/pyanaconda/nm.py b/pyanaconda/nm.py
index 3c587dc..17b765d 100644
--- a/pyanaconda/nm.py
+++ b/pyanaconda/nm.py
@@ -440,6 +440,29 @@ def nm_device_ip_config(name, version=4):
return [addr_list, ns_list]
+def nm_device_slaves(name):
+ """Return slaves of device.
+
+ :param name: name of device
+ :type name: str
+ :return: names of slaves of device or None if device has no 'Slaves' property
+ :rtype: list of strings or None
+ :raise UnknownDeviceError if device is not found
+ """
+
+ try:
+ slaves = nm_device_property(name, "Slaves")
+ except PropertyNotFoundError:
+ return None
+
+ slave_ifaces = []
+ for slave in slaves:
+ iface = _get_property(slave, "Interface", ".Device")
+ slave_ifaces.append(iface)
+
+ return slave_ifaces
+
+
def nm_ntp_servers_from_dhcp():
"""Return NTP servers obtained by DHCP.
--
1.7.11.7
10 years, 8 months
[PATCH] Cleanup some pylint failures in the network module
by Brian C. Lane
From: "Brian C. Lane" <bcl(a)redhat.com>
---
pyanaconda/network.py | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/pyanaconda/network.py b/pyanaconda/network.py
index dcb6ee0..f2f28a9 100644
--- a/pyanaconda/network.py
+++ b/pyanaconda/network.py
@@ -226,18 +226,18 @@ class IfcfgFile(SimpleConfigFile):
SimpleConfigFile.__init__(self, always_quote=True, filename=filename)
self._dirty = False
- def read(self):
+ def read(self, filename=None):
self.reset()
ifcfglog.debug("IfcfFile.read %s", self.filename)
SimpleConfigFile.read(self)
self._dirty = False
- def write(self, filename=None):
+ def write(self, filename=None, use_tmp=False):
if self._dirty or filename:
# ifcfg-rh is using inotify IN_CLOSE_WRITE event so we don't use
# temporary file for new configuration
ifcfglog.debug("IfcfgFile.write %s:\n%s", self.filename, self.__str__())
- SimpleConfigFile.write(self, filename, use_tmp=False)
+ SimpleConfigFile.write(self, filename, use_tmp=use_tmp)
self._dirty = False
def set(self, *args):
@@ -582,7 +582,6 @@ def ifcfg_to_ksdata(ifcfg, devname):
def hostname_ksdata(hostname):
from pyanaconda.kickstart import AnacondaKSHandler
handler = AnacondaKSHandler()
- kwargs = {}
# pylint: disable-msg=E1101
return handler.NetworkData(hostname=hostname, bootProto="")
@@ -1047,6 +1046,7 @@ def status_message():
slaves = {}
ssids = {}
nonslaves = []
+ devname = ""
# first find slaves and wireless aps
for devname in active_devs:
--
1.8.3.1
10 years, 8 months
[master/rhel7] LiveImageKSPayload skip the parent class setup method (#1010500)
by Brian C. Lane
From: "Brian C. Lane" <bcl(a)redhat.com>
LiveImageKSPayload mounts the image itself, so call the ImagePayload
setup method instead.
Resolves: rhbz#1010500
---
pyanaconda/packaging/livepayload.py | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/pyanaconda/packaging/livepayload.py b/pyanaconda/packaging/livepayload.py
index 377dc46..b9a4814 100644
--- a/pyanaconda/packaging/livepayload.py
+++ b/pyanaconda/packaging/livepayload.py
@@ -210,7 +210,8 @@ class LiveImageKSPayload(LiveImagePayload):
def setup(self, storage):
""" Check the availability and size of the image.
"""
- super(LiveImageKSPayload, self).setup(storage)
+ # This is on purpose, we don't want to call LiveImagePayload's setup method.
+ ImagePayload.setup(self, storage)
self._proxies = {}
if self.data.method.proxy:
--
1.8.3.1
10 years, 8 months
[PATCH] Add GtkNotebook support to the acclerators check.
by David Shea
This removes the need for most of the exception comments. The only
exceptions left are one in installation source where elements are shown
and hidden based on a radio button selection, and one in the iscsi login
where elements are shown and hidden based on a dropdown.
---
pyanaconda/ui/gui/spokes/advstorage/iscsi.glade | 11 +-
pyanaconda/ui/gui/spokes/custom.glade | 2 -
pyanaconda/ui/gui/spokes/filter.glade | 7 --
pyanaconda/ui/gui/spokes/network.glade | 4 -
tests/accelerators/check_accelerators.py | 150 ++++++++++++++++++------
5 files changed, 117 insertions(+), 57 deletions(-)
diff --git a/pyanaconda/ui/gui/spokes/advstorage/iscsi.glade b/pyanaconda/ui/gui/spokes/advstorage/iscsi.glade
index 98fb46f..208122a 100644
--- a/pyanaconda/ui/gui/spokes/advstorage/iscsi.glade
+++ b/pyanaconda/ui/gui/spokes/advstorage/iscsi.glade
@@ -397,7 +397,6 @@
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="xalign">0</property>
- <!-- check_accelerators: not visible at same time as label2 -->
<property name="label" translatable="yes">CHAP _Username:</property>
<property name="use_underline">True</property>
<property name="mnemonic_widget">rchapUsernameEntry</property>
@@ -414,7 +413,6 @@
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="xalign">0</property>
- <!-- check_accelerators: not visible at same time as label3 -->
<property name="label" translatable="yes">CHAP _Password:</property>
<property name="use_underline">True</property>
<property name="mnemonic_widget">rchapPasswordEntry</property>
@@ -764,7 +762,6 @@
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="xalign">0</property>
- <!-- check_accelerators: not visible at same time as label11 -->
<property name="label" translatable="yes">_Node login authentication type:</property>
<property name="use_underline">True</property>
<property name="mnemonic_widget">loginAuthTypeCombo</property>
@@ -823,7 +820,6 @@
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="xalign">0</property>
- <!-- check_accelerators: not visible at same time as label2 -->
<property name="label" translatable="yes">CHAP _Username:</property>
<property name="use_underline">True</property>
<property name="mnemonic_widget">loginChapUsernameEntry</property>
@@ -840,7 +836,6 @@
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="xalign">0</property>
- <!-- check_accelerators: not visible at same time as label3 -->
<property name="label" translatable="yes">CHAP _Password:</property>
<property name="use_underline">True</property>
<property name="mnemonic_widget">loginChapPasswordEntry</property>
@@ -967,7 +962,6 @@
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="xalign">0</property>
- <!-- check_accelerators: not visible at same time as label2 -->
<property name="label" translatable="yes">CHAP _Username:</property>
<property name="use_underline">True</property>
<property name="mnemonic_widget">loginRchapUsernameEntry</property>
@@ -984,7 +978,6 @@
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="xalign">0</property>
- <!-- check_accelerators: not visible at same time as label3 -->
<property name="label" translatable="yes">CHAP _Password:</property>
<property name="use_underline">True</property>
<property name="mnemonic_widget">loginRchapPasswordEntry</property>
@@ -1001,7 +994,6 @@
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="xalign">0</property>
- <!-- check_accelerators: not visible at same time as retryButton -->
<property name="label" translatable="yes">_Reverse CHAP Username:</property>
<property name="use_underline">True</property>
<property name="mnemonic_widget">loginRchapReverseUsername</property>
@@ -1018,7 +1010,6 @@
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="xalign">0</property>
- <!-- check_accelerators: not visible at same time as label12 -->
<property name="label" translatable="yes">Reverse CHAP Pass_word:</property>
<property name="use_underline">True</property>
<property name="mnemonic_widget">loginRchapReversePassword</property>
@@ -1170,7 +1161,7 @@
</child>
<child>
<object class="GtkButton" id="retryLoginButton">
- <!-- check_accelerators: not visible at same time as retryButton -->
+ <!-- check_accelerators: not visible at same time as label19 -->
<property name="label" translatable="yes">_Retry Log In</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
diff --git a/pyanaconda/ui/gui/spokes/custom.glade b/pyanaconda/ui/gui/spokes/custom.glade
index 1b5de13..2c45c5f 100644
--- a/pyanaconda/ui/gui/spokes/custom.glade
+++ b/pyanaconda/ui/gui/spokes/custom.glade
@@ -1364,7 +1364,6 @@ until you click on the main menu's 'Begin Installation' button.</property>
<object class="GtkLabel" id="passphraseLabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
- <!-- check_accelerators: not visible at same time as mountPointLabel -->
<property name="label" translatable="yes">_Passphrase:</property>
<property name="use_underline">True</property>
<attributes>
@@ -1393,7 +1392,6 @@ until you click on the main menu's 'Begin Installation' button.</property>
</child>
<child>
<object class="GtkButton" id="unlockButton">
- <!-- check_accelerators: not visible at same time as applyButton -->
<property name="label" translatable="yes">_Unlock</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
diff --git a/pyanaconda/ui/gui/spokes/filter.glade b/pyanaconda/ui/gui/spokes/filter.glade
index e98ed1a..8c50349 100644
--- a/pyanaconda/ui/gui/spokes/filter.glade
+++ b/pyanaconda/ui/gui/spokes/filter.glade
@@ -641,7 +641,6 @@
<object class="GtkLabel" id="label16">
<property name="visible">True</property>
<property name="can_focus">False</property>
- <!-- check_accelerators: not visible at same time as label7 -->
<property name="label" translatable="yes">Show Only _Devices With:</property>
<property name="use_underline">True</property>
<property name="mnemonic_widget">multipathInterconnectCombo</property>
@@ -682,7 +681,6 @@
<object class="GtkLabel" id="label17">
<property name="visible">True</property>
<property name="can_focus">False</property>
- <!-- check_accelerators: not visible at same time as label7 -->
<property name="label" translatable="yes">Show Only _Devices Containing:</property>
<property name="use_underline">True</property>
<property name="mnemonic_widget">multipathWWIDEntry</property>
@@ -901,7 +899,6 @@
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="xalign">0</property>
- <!-- check_accelerators: not visible at same time as label2 -->
<property name="label" translatable="yes">_Filter By:</property>
<property name="use_underline">True</property>
<property name="mnemonic_widget">multipathTypeCombo</property>
@@ -960,7 +957,6 @@
<object class="GtkLabel" id="label12">
<property name="visible">True</property>
<property name="can_focus">False</property>
- <!-- check_accelerators: not visible at same time as label7 -->
<property name="label" translatable="yes">Show Only _Devices From:</property>
<property name="use_underline">True</property>
<property name="mnemonic_widget">otherVendorCombo</property>
@@ -1001,7 +997,6 @@
<object class="GtkLabel" id="label20">
<property name="visible">True</property>
<property name="can_focus">False</property>
- <!-- check_accelerators: not visible at same time as label7 -->
<property name="label" translatable="yes">Show Only _Devices With:</property>
<property name="use_underline">True</property>
<property name="mnemonic_widget">otherInterconnectCombo</property>
@@ -1042,7 +1037,6 @@
<object class="GtkLabel" id="label21">
<property name="visible">True</property>
<property name="can_focus">False</property>
- <!-- check_accelerators: not visible at same time as label7 -->
<property name="label" translatable="yes">Show Only _Devices Containing:</property>
<property name="use_underline">True</property>
<property name="mnemonic_widget">otherIDEntry</property>
@@ -1272,7 +1266,6 @@
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="xalign">0</property>
- <!-- check_accelerators: not visible at same time as label2 -->
<property name="label" translatable="yes">_Filter By:</property>
<property name="use_underline">True</property>
<property name="mnemonic_widget">zFilterCombo</property>
diff --git a/pyanaconda/ui/gui/spokes/network.glade b/pyanaconda/ui/gui/spokes/network.glade
index 14ec157..5701e68 100644
--- a/pyanaconda/ui/gui/spokes/network.glade
+++ b/pyanaconda/ui/gui/spokes/network.glade
@@ -1641,7 +1641,6 @@ updates available for you.</property>
<property name="top_padding">12</property>
<child>
<object class="GtkButton" id="button_mobilebb_options">
- <!-- check_accelerators: not in same tab as button_wireless_options -->
<property name="label" translatable="yes">_Configure...</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
@@ -1927,7 +1926,6 @@ updates available for you.</property>
<property name="top_padding">12</property>
<child>
<object class="GtkButton" id="button_vpn_options">
- <!-- check_accelerators: not in same tab as button_wireless_options -->
<property name="label" translatable="yes">_Configure...</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
@@ -2083,7 +2081,6 @@ updates available for you.</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="xalign">1</property>
- <!-- check_accelerators: not in same tab as button_wireless_options -->
<property name="label" translatable="yes">_Configuration URL</property>
<property name="use_underline">True</property>
<property name="mnemonic_widget">entry_proxy_url</property>
@@ -2162,7 +2159,6 @@ updates available for you.</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="xalign">1</property>
- <!-- check_accelerators: not in same tab as button_wireless_options -->
<property name="label" translatable="yes">_Socks Host</property>
<property name="use_underline">True</property>
<property name="mnemonic_widget">entry_proxy_socks</property>
diff --git a/tests/accelerators/check_accelerators.py b/tests/accelerators/check_accelerators.py
index dff3c3f..e4a5f56 100755
--- a/tests/accelerators/check_accelerators.py
+++ b/tests/accelerators/check_accelerators.py
@@ -21,6 +21,7 @@ import sys
import argparse
import re
import os.path
+import copy
try:
from lxml import etree
@@ -30,55 +31,136 @@ except ImportError:
accel_re = re.compile(r'_(?P<accel>.)')
+success = True
+def add_check_accel(glade_filename, accels, label):
+ """Check whether an accelerator conflicts with existing accelerators.
+ and add it to the current accelerator context.
+ """
+ global success
+
+ match = accel_re.search(label.text)
+ if match:
+ accel = match.group('accel').lower()
+ if accel in accels:
+ # Check for an exception comment
+ prev = label.getprevious()
+ if (prev is not None) and (prev.tag == etree.Comment) and \
+ prev.text.strip().startswith('check_accelerators:'):
+ return
+
+ print("Accelerator collision for key %s in %s\n line %d: %s\n line %d: %s" %\
+ (accel, os.path.normpath(glade_filename),
+ accels[accel].sourceline, accels[accel].text,
+ label.sourceline, label.text))
+ success = False
+ else:
+ accels[accel] = label
+
+def combine_accels(glade_filename, list_a, list_b):
+ if not list_a:
+ return list_b
+ if not list_b:
+ return list_a
+
+ newlist = []
+ for accels_a in list_a:
+ for accels_b in list_b:
+ new_accels = copy.copy(accels_a)
+ for accel in accels_b.keys():
+ add_check_accel(glade_filename, new_accels, accels_b[accel])
+ newlist.append(new_accels)
+ return newlist
+
+# GtkNotebook widgets define several child widgets, not all of which are active
+# at the same time. To further complicate things, an object can have more than
+# one GtkNotebook child, and a GtkNotebook and have GtkNotebook children.
+#
+# To handle this, GtkNotebook objects are processed separately.
+# process_notebook returns a list of possible accelerator lists, and each of
+# these is compared against the list of accelerators returned for the object's
+# other GtkNotebook children.
+
+def process_object(glade_filename, interface_object):
+ """Process keyboard shortcuts for a given glade object.
+
+ The return value from this function is a list of accelerator
+ dictionaries, with each consiting of accelerator shortcut characters
+ as keys and the corresponding <object> Element objects as values. Each
+ dictionary represents a set of accelerators that could be active at any
+ given time.
+ """
+ # Start with an empty context for things that are always active
+ accels = [{}]
+
+ # Add everything that isn't a child of a GtkNotebook
+ for label in interface_object.xpath(".//property[@name='label' and ../property[@name='use_underline']/text() = 'True' and not(ancestor::object[@class='GtkNotebook'])]"):
+ add_check_accel(glade_filename, accels[0], label)
+
+ # For each GtkNotebook tab that is not a child of another notebook,
+ # add the tab to the top-level context
+ for notebook_label in interface_object.xpath(".//object[@class='GtkNotebook' and not(ancestor::object[@class='GtkNotebook'])]/child[@type='tab']//property[@name='label' and ../property[@name='use_underline']/text() = 'True']"):
+ add_check_accel(glade_filename, accels[0], notebook_label)
+
+ # Now process each non-tab object in each Gtknotebook that is not a child
+ # of another notebook. For each Gtk notebook, each non-tab child represents
+ # a separate potentially-active context. Since each list returned by
+ # process_object for a GtkNotebook child is independent of each other
+ # GtkNotebook child, we can just combine all of them into a single list.
+ # For example, say there's a notebook with two panes. The first pane
+ # contains another notebook with two panes. Let's call the main pane
+ # A, and the panes in the child GtkNotebook A_1 and A_2. A contains an
+ # accelerator for 'a', A_1 contains accelerators for 'b' and 'c', and A_2
+ # contains accelerators for 'b' and 'c'. The list returned would look like:
+ # [{'a': label1, 'b': label2, 'c': label3},
+ # {'a': label1, 'b': label4, 'c': label5}]
+ # Then when we process the other pane in the Notebook that contains A
+ # (let's call it B), we find acclerators for 'a' and 'b':
+ # [{'a': label6, 'b': label7}].
+ # None of these dictionaries are active at the same time. Because
+ # process_object on A combined the accelerators that are in the top-level
+ # of A with each of the accelerators in the Notebook children of A, we can
+ # treat A as if it were actually two panes at the same-level of B and just
+ # create a list of three dictionaries for the whole notebook.
+ #
+ # A deepcopy of each object is taken so that the object can be treated as a
+ # separate XML document so that the ancestor axis stuff works.
+
+ for notebook in interface_object.xpath(".//object[@class='GtkNotebook' and not(ancestor::object[@class='GtkNotebook'])]"):
+ # Create the list of dictionaries for the notebook
+ notebook_list = []
+ for child in notebook.xpath("./child[not(@type='tab')]"):
+ notebook_list.extend(process_object(glade_filename, copy.deepcopy(child)))
+
+ # Now combine this with our list of accelerators
+ accels = combine_accels(glade_filename, accels, notebook_list)
+
+ return accels
+
def check_glade(glade_filename):
- success = True
with open(glade_filename) as glade_file:
# Parse the XML
glade_tree = etree.parse(glade_file)
- # Assume that each top-level object is a separate context
+ # Treat each top-level object as a separate context
for interface_object in glade_tree.xpath("/interface/object"):
- accels = {}
-
- # Select the label properties of objects whose use_underline
- # property is true.
- # NB: This is why we can't use python's builtin etree
- for label in interface_object.xpath(".//property[@name='label' and ../property[@name='use_underline']/text() = 'True']"):
- match = accel_re.search(label.text)
- if match:
- accel = match.group('accel').lower()
- if accel in accels:
- # Check for an exception comment
- prev = label.getprevious()
- if (prev is not None) and (prev.tag == etree.Comment) and \
- prev.text.strip().startswith('check_accelerators:'):
- continue
-
- print("Accelerator collision for key %s in %s:%s\n line %d: %s\n line %d: %s" %\
- (accel, os.path.normpath(glade_filename), interface_object.attrib['id'],
- accels[accel].sourceline, accels[accel].text,
- label.sourceline, label.text))
- success = False
- else:
- accels[accel] = label
- return success
-
-def main(argv=sys.argv):
+ process_object(glade_filename, interface_object)
+
+def main(argv=None):
+ if argv is None:
+ argv = sys.argv
+
parser = argparse.ArgumentParser("Check for duplicated accelerators")
parser.add_argument("glade_files", nargs="+", metavar="GLADE-FILE",
help='The glade file to check')
args = parser.parse_args(args=argv)
- success = True
for glade_file in args.glade_files:
- if not check_glade(glade_file):
- success = False
- return success
+ check_glade(glade_file)
if __name__ == "__main__":
- result = main(sys.argv[1:])
+ main(sys.argv[1:])
- if result:
+ if success:
sys.exit(0)
else:
sys.exit(1)
--
1.8.3.1
10 years, 9 months
[PATCH] Encrypt normal user passwords when doing text install. (#977732)
by Samantha N. Bueno
There isn't currently a bug against it, but I'd really like to see this
go into rhel7-branch as well. Thoughts?
====
More than simply mirroring graphical behavior, passwords shouldn't
be stored plaintext in the first place.
---
pyanaconda/ui/tui/spokes/__init__.py | 6 ++++--
pyanaconda/ui/tui/spokes/user.py | 16 ++++++++++++++--
2 files changed, 18 insertions(+), 4 deletions(-)
diff --git a/pyanaconda/ui/tui/spokes/__init__.py b/pyanaconda/ui/tui/spokes/__init__.py
index 087199b..773ea67 100644
--- a/pyanaconda/ui/tui/spokes/__init__.py
+++ b/pyanaconda/ui/tui/spokes/__init__.py
@@ -226,8 +226,10 @@ class EditTUISpoke(NormalTUISpoke):
def _prep_password(i, entry):
number = tui.TextWidget("%2d)" % i)
title = tui.TextWidget(_(entry.title))
- value = getdeepattr(self.args, entry.attribute)
- value = tui.TextWidget("".join(["*"] * len(value)))
+ value = ""
+ if len(getdeepattr(self.args, entry.attribute)) > 0:
+ value = _("Password set.")
+ value = tui.TextWidget(value)
return tui.ColumnWidget([(3, [number]), (None, [title, value])], 1)
diff --git a/pyanaconda/ui/tui/spokes/user.py b/pyanaconda/ui/tui/spokes/user.py
index 6185f80..2b0d3f2 100644
--- a/pyanaconda/ui/tui/spokes/user.py
+++ b/pyanaconda/ui/tui/spokes/user.py
@@ -1,4 +1,4 @@
-# Root password text spoke
+# User creation text spoke
#
# Copyright (C) 2013 Red Hat, Inc.
#
@@ -22,7 +22,7 @@
from pyanaconda.ui.tui.spokes import EditTUISpoke
from pyanaconda.ui.tui.spokes import EditTUISpokeEntry as Entry
from pyanaconda.ui.common import FirstbootSpokeMixIn
-from pyanaconda.users import guess_username
+from pyanaconda.users import guess_username, cryptPassword
from pyanaconda.i18n import _
from pykickstart.constants import FIRSTBOOT_RECONFIG
from pyanaconda.constants import ANACONDA_ENVIRON, FIRSTBOOT_ENVIRON
@@ -123,3 +123,15 @@ class UserSpoke(FirstbootSpokeMixIn, EditTUISpoke):
self.data.user.userList.append(self.args)
elif (not self.args._create) and (self.args in self.data.user.userList):
self.data.user.userList.remove(self.args)
+
+ # encrypt and store password only if user entered anything; this should
+ # preserve passwords set via kickstart
+ if self.args._use_password and len(self.args.password) > 0:
+ self.args.password = cryptPassword(self.args.password)
+ self.args.isCrypted = True
+ self.args.password_kickstarted = False
+ # clear pw when user unselects to use pw
+ else:
+ self.args.password = ""
+ self.args.isCrypted = False
+ self.args.password_kickstarted = False
--
1.7.11.7
10 years, 9 months
[PATCH] Forbid "root" as a user or group name. (#968451)
by David Shea
This also fixes the handling of single-character names, which were
mistakenly forbidden before.
---
pyanaconda/regexes.py | 7 +++++--
tests/regex_tests/username_test.py | 16 ++++++++++++----
2 files changed, 17 insertions(+), 6 deletions(-)
diff --git a/pyanaconda/regexes.py b/pyanaconda/regexes.py
index 44acc0b..5859e59 100644
--- a/pyanaconda/regexes.py
+++ b/pyanaconda/regexes.py
@@ -38,10 +38,13 @@ GECOS_VALID = re.compile(r'^[^:]*$')
# and UT_NAMESIZE for user names (which is defined as 32 bits/utmp.h). This
# expression captures all of that: the initial character, followed by either
# up to 30 portable characters and a dollar sign or up to 31 portable characters,
-# both for a maximum total of 32. The empty string is not allowed.
+# both for a maximum total of 32. The empty string is not allowed. "root" is not
+# allowed.
# a base expression without anchors, helpful for building other expressions
-_USERNAME_BASE = r'[a-zA-Z0-9._](([a-zA-Z0-9._-]{,30}\$)|([a-zA-Z0-9._-]{,31}))'
+# If the string is the right length to match "root", use a lookback expression
+# to make sure it isn't.
+_USERNAME_BASE = r'[a-zA-Z0-9._](([a-zA-Z0-9._-]{1,2})|([a-zA-Z0-9._-]{3}(?<!root))|([a-zA-Z0-9._-]{,30}\$)|([a-zA-Z0-9._-]{4,31}))?'
USERNAME_VALID = re.compile(r'^' + _USERNAME_BASE + '$')
GROUPNAME_VALID = USERNAME_VALID
diff --git a/tests/regex_tests/username_test.py b/tests/regex_tests/username_test.py
index 9877410..0c0d5d2 100644
--- a/tests/regex_tests/username_test.py
+++ b/tests/regex_tests/username_test.py
@@ -29,14 +29,14 @@ class UsernameRegexTestCase(unittest.TestCase):
for good in goodlist:
try:
self.assertIsNotNone(expression.match(good))
- except AssertionError as error:
+ except AssertionError:
got_error = True
print("Good string %s did not match expression" % good)
for bad in badlist:
try:
self.assertIsNone(expression.match(bad))
- except AssertionError as error:
+ except AssertionError:
got_error = True
print("Bad string %s matched expression" % bad)
@@ -70,7 +70,12 @@ class UsernameRegexTestCase(unittest.TestCase):
'g_burdell',
'_burdell',
'gggggggggggggggggggggggggburdell', # 32 characters
- 'ggggggggggggggggggggggggburdell$'
+ 'ggggggggggggggggggggggggburdell$',
+ '_',
+ 'r',
+ 'ro',
+ 'roo',
+ 'roota',
]
bad_tests = [
@@ -83,7 +88,10 @@ class UsernameRegexTestCase(unittest.TestCase):
'ggggggggggggggggggggggggggburdell', # 33 characters
'gggggggggggggggggggggggggburdell$',
' gburdell',
- ':gburdell'
+ ':gburdell',
+ 'root',
+ '$',
+ '-'
]
self._run_tests(USERNAME_VALID, good_tests, bad_tests)
--
1.8.3.1
10 years, 9 months
[master/rhel7-branch] Make it obvious user is going to begin installation in TUI. (#975793)
by Samantha N. Bueno
Re-post of a patch from forever ago that needed a little work. This
should only require very minimal tweaking for rhel7-branch.
This tweaks the global default prompt for the new option ('b' to
begin installation), so it should now be very clear to users that they
are about to kick off installation.
This also adds a default prompt for spokes, as many of them need to have
the 'c' to continue option, and it is probably best to just have 'b' to
begin installation on the summary hub anyhow.
End result looks like this:
http://sbueno.fedorapeople.org/images/975793-revised.jpg
Resolves: rhbz#975793
---
pyanaconda/ui/tui/hubs/__init__.py | 2 +-
pyanaconda/ui/tui/simpleline/base.py | 6 +++---
pyanaconda/ui/tui/spokes/__init__.py | 10 ++++++++--
pyanaconda/ui/tui/spokes/network.py | 3 +++
4 files changed, 15 insertions(+), 6 deletions(-)
diff --git a/pyanaconda/ui/tui/hubs/__init__.py b/pyanaconda/ui/tui/hubs/__init__.py
index 8f219c3..be78b32 100644
--- a/pyanaconda/ui/tui/hubs/__init__.py
+++ b/pyanaconda/ui/tui/hubs/__init__.py
@@ -109,7 +109,7 @@ class TUIHub(TUIObject, common.Hub):
# If we get a continue, check for unfinished spokes. If unfinished
# don't continue
# TRANSLATORS: 'c' to continue
- if key == _('c'):
+ if key == _('b'):
for spoke in self._spokes.values():
if not spoke.completed and spoke.mandatory:
print(_("Please complete all spokes before continuing"))
diff --git a/pyanaconda/ui/tui/simpleline/base.py b/pyanaconda/ui/tui/simpleline/base.py
index 8c2424b..a02373f 100644
--- a/pyanaconda/ui/tui/simpleline/base.py
+++ b/pyanaconda/ui/tui/simpleline/base.py
@@ -455,8 +455,8 @@ class App(object):
return True
# global close command
- # TRANSLATORS: 'c' to continue
- if self._screens and (key == _('c')):
+ # TRANSLATORS: 'b' to begin installation
+ if self._screens and (key == _('b')):
self.close_screen()
return True
@@ -582,7 +582,7 @@ class UIScreen(object):
to skip further input processing
:rtype: unicode|None
"""
- return _(u" Please make your choice from above ['q' to quit | 'c' to continue |\n 'r' to refresh]: ")
+ return _(u" Please make your choice from above ['q' to quit | 'b' to begin installation |\n 'r' to refresh]: ")
@property
def app(self):
diff --git a/pyanaconda/ui/tui/spokes/__init__.py b/pyanaconda/ui/tui/spokes/__init__.py
index 087199b..075af60 100644
--- a/pyanaconda/ui/tui/spokes/__init__.py
+++ b/pyanaconda/ui/tui/spokes/__init__.py
@@ -84,7 +84,8 @@ class TUISpoke(TUIObject, tui.Widget, Spoke):
self.draw(c)
class NormalTUISpoke(TUISpoke, NormalSpoke):
- pass
+ def prompt(self, args=None):
+ return _(u" Please make your choice from above ['q' to quit | 'c' to continue] ")
EditTUISpokeEntry = namedtuple("EditTUISpokeEntry", ["title", "attribute", "aux", "visible"])
@@ -266,7 +267,12 @@ class EditTUISpoke(NormalTUISpoke):
self.apply()
return True
except ValueError:
- pass
+ # Translators: 'c' to continue
+ if key.lower() == _("c"):
+ self.close()
+ return True
+ else:
+ pass
return NormalTUISpoke.input(self, args, key)
diff --git a/pyanaconda/ui/tui/spokes/network.py b/pyanaconda/ui/tui/spokes/network.py
index a432bcb..0ada2a4 100644
--- a/pyanaconda/ui/tui/spokes/network.py
+++ b/pyanaconda/ui/tui/spokes/network.py
@@ -178,6 +178,9 @@ class NetworkSpoke(EditTUISpoke):
try:
num = int(key)
except ValueError:
+ if key.lower() == _("c"):
+ self.close()
+ return INPUT_PROCESSED
return key
if num == 1:
--
1.7.11.7
10 years, 9 months
[rhel6-branch][PATCH] Do not select FS packages over and over (#994504)
by Vratislav Podzimek
Instead of selecting FS packages for every device we can build a set of packages
that should be selected for all devices and do it only once. This speeds up the
installation on systems with many devices a lot.
Signed-off-by: Vratislav Podzimek <vpodzime(a)redhat.com>
---
yuminstall.py | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/yuminstall.py b/yuminstall.py
index ef92d79..82923ae 100644
--- a/yuminstall.py
+++ b/yuminstall.py
@@ -1578,9 +1578,12 @@ debuglevel=6
selectKernel("kernel")
def selectFSPackages(self, storage):
+ fspkgs = set()
for device in storage.fsset.devices:
# this takes care of device and filesystem packages
- map(self.selectPackage, device.packages)
+ for pkg in device.packages:
+ fspkgs.add(pkg)
+ map(self.selectPackage, fspkgs)
# anaconda requires several programs on the installed system to complete
# installation, but we have no guarantees that some of these will be
--
1.7.11.7
10 years, 9 months