[PATCH] Fix handling of flexible specs in onpart for member devices. (#1004885)
by David Lehman
Short version: don't assume onPart identifier is a name/path.
Longer version:
If an existing pv was specified using --onpart=UUID=<uuid> the
immediate onpart resolution worked, but the volgroup would then fail
to resolve the pv.xxx to a device because it assumed the onpart data
was a name.
---
pyanaconda/kickstart.py | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/pyanaconda/kickstart.py b/pyanaconda/kickstart.py
index e3f8895..d6baaaa 100644
--- a/pyanaconda/kickstart.py
+++ b/pyanaconda/kickstart.py
@@ -314,7 +314,7 @@ class BTRFSData(commands.btrfs.F17_BTRFSData):
# if using --onpart, use original device
member_name = ksdata.onPart.get(member, member)
if member_name:
- dev = devicetree.getDeviceByName(member_name) or lookupAlias(devicetree, member)
+ dev = devicetree.getDeviceByName(udev.udev_resolve_devspec(member_name)) or lookupAlias(devicetree, member)
if not dev:
dev = devicetree.resolveDevice(member)
@@ -1131,7 +1131,7 @@ class RaidData(commands.raid.F18_RaidData):
for member in self.members:
# if member is using --onpart, use original device
mem = ksdata.onPart.get(member, member)
- dev = devicetree.getDeviceByName(mem) or lookupAlias(devicetree, mem)
+ dev = devicetree.getDeviceByName(udev.udev_resolve_devspec(mem)) or lookupAlias(devicetree, mem)
if dev and dev.format.type == "luks":
try:
dev = devicetree.getChildren(dev)[0]
@@ -1350,7 +1350,7 @@ class VolGroupData(commands.volgroup.FC16_VolGroupData):
for pv in self.physvols:
# if pv is using --onpart, use original device
pv = ksdata.onPart.get(pv, pv)
- dev = devicetree.getDeviceByName(pv) or lookupAlias(devicetree, pv)
+ dev = devicetree.getDeviceByName(udev.udev_resolve_devspec(pv)) or lookupAlias(devicetree, pv)
if dev and dev.format.type == "luks":
try:
dev = devicetree.getChildren(dev)[0]
--
1.8.1.4
10 years, 8 months
[rhel6-branch] Drop support for ssh protocol version 1 (#1004752)
by Brian C. Lane
From: "Brian C. Lane" <bcl(a)redhat.com>
In fips mode creation of the protocol 1 key causes it to hang. This
removes version 1 support during installation. It has no effect on the
installed system.
---
anaconda | 1 -
scripts/mk-images | 5 -----
2 files changed, 6 deletions(-)
diff --git a/anaconda b/anaconda
index 0e566f3..09d11c2 100755
--- a/anaconda
+++ b/anaconda
@@ -459,7 +459,6 @@ def startSsh():
if not fork_orphan():
os.open("/var/log/lastlog", os.O_RDWR | os.O_CREAT, 0644)
ssh_keys = {
- 'rsa1':'ssh_host_key',
'rsa':'ssh_host_rsa_key',
'dsa':'ssh_host_dsa_key',
}
diff --git a/scripts/mk-images b/scripts/mk-images
index eb2b26a..2439002 100755
--- a/scripts/mk-images
+++ b/scripts/mk-images
@@ -475,10 +475,6 @@ EOF
# key generation takes ages on s390, you really don't want this
# for every installation attempt. These are NOT the keys of the
# installed system!
- echo -n "Generating SSH1 RSA host key: "
- /usr/bin/ssh-keygen -q -t rsa1 -f $MBD_DIR/etc/ssh/ssh_host_key \
- -C '' -N '' >&/dev/null
- echo
echo -n "Generating SSH2 RSA host key: "
/usr/bin/ssh-keygen -q -t rsa -f $MBD_DIR/etc/ssh/ssh_host_rsa_key \
-C '' -N '' >&/dev/null
@@ -494,7 +490,6 @@ EOF
cat > $MBD_DIR/etc/ssh/sshd_config.anaconda <<EOF
Port 22
-HostKey /etc/ssh/ssh_host_key
HostKey /etc/ssh/ssh_host_rsa_key
HostKey /etc/ssh/ssh_host_dsa_key
PermitRootLogin yes
--
1.8.3.1
10 years, 8 months
[master/rhel7] Add more details to iso device selector (#971290)
by Brian C. Lane
From: "Brian C. Lane" <bcl(a)redhat.com>
Add the device path, format and label or uuid to the dropdown. uuid is
only shown if there is no label.
-- See and example here: http://bcl.fedorapeople.org/images/isofile.png
---
pyanaconda/ui/gui/spokes/source.py | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/pyanaconda/ui/gui/spokes/source.py b/pyanaconda/ui/gui/spokes/source.py
index 8dd8ba2..e8fb3c5 100644
--- a/pyanaconda/ui/gui/spokes/source.py
+++ b/pyanaconda/ui/gui/spokes/source.py
@@ -625,7 +625,14 @@ class SourceSpoke(NormalSpoke):
active = 0
idx = 0
for dev in potentialHdisoSources(self.storage.devicetree):
- store.append([dev, "%s (%s MB)" % (self._sanitize_model(dev.disk.model), int(dev.size))])
+ # path model size format type uuid of format
+ dev_info = { "model" : self._sanitize_model(dev.disk.model),
+ "path" : dev.path,
+ "size" : dev.size,
+ "format": dev.format.name or "",
+ "label" : dev.format.label or dev.format.uuid or ""
+ }
+ store.append([dev, "%(model)s %(path)s (%(size)s MB) %(format)s %(label)s" % dev_info])
if self.data.method.method == "harddrive" and dev.name == self.data.method.partition:
active = idx
added = True
--
1.8.3.1
10 years, 8 months
[master] Test case fixes
by David Shea
Some tests were failing, some tests were being skipped, and some tests didn't
run with the right paths because automake was setting more environment
variables than I thought it would. These patches fix all of that.
Hey clumens welcome back we got you a present:
============================================================================
Testsuite summary for anaconda 20.12
============================================================================
# TOTAL: 3
# PASS: 3
# SKIP: 0
# XFAIL: 0
# FAIL: 0
# XPASS: 0
# ERROR: 0
============================================================================
10 years, 8 months
[PATCH] Fix check for device state when reading its IPXConfig (#1001776)
by Radek Vykydal
Device has to be in ACTIVATED state for IPXConfig to be valid.
1) use a recently added nm module function to get IP configuration, replacing
python-dbus with GDBus here. Python-dbus would give us stale value.
2) Don't use get_cached_property of GDBus as it would give us stale value too.
Instead use DBus.Properties interface call to get current values.
---
pyanaconda/nm.py | 77 ++++++++++++++++++++-----------------
pyanaconda/ui/gui/spokes/network.py | 64 +++++++++++-------------------
2 files changed, 63 insertions(+), 78 deletions(-)
diff --git a/pyanaconda/nm.py b/pyanaconda/nm.py
index 1109d6e..4f0923d 100644
--- a/pyanaconda/nm.py
+++ b/pyanaconda/nm.py
@@ -73,10 +73,27 @@ def _get_proxy(bus_type=Gio.BusType.SYSTEM,
cancellable)
return proxy
+def _get_property(object_path, prop, interface_name_suffix=""):
+ interface_name = "org.freedesktop.NetworkManager" + interface_name_suffix
+ proxy = _get_proxy(object_path=object_path, interface_name="org.freedesktop.DBus.Properties")
+ args = GLib.Variant('(ss)', (interface_name, prop))
+ try:
+ prop = proxy.call_sync("Get",
+ args,
+ Gio.DBusCallFlags.NONE,
+ DEFAULT_DBUS_TIMEOUT,
+ None)
+ except GLib.GError as e:
+ if "org.freedesktop.DBus.Error.AccessDenied" in e.message:
+ return None
+ else:
+ raise
+
+ return prop.unpack()[0]
+
def nm_state():
"""Return state of NetworkManager"""
- proxy = _get_proxy()
- return proxy.get_cached_property("State").unpack()
+ return _get_property("/org/freedesktop/NetworkManager", "State")
# FIXME - use just GLOBAL? There is some connectivity checking
# for GLOBAL in NM (nm_connectivity_get_connected), not sure if
@@ -107,11 +124,11 @@ def nm_devices():
devices = devices.unpack()[0]
for device in devices:
- proxy = _get_proxy(object_path=device, interface_name="org.freedesktop.NetworkManager.Device")
- device_type = proxy.get_cached_property("DeviceType").unpack()
+ device_type = _get_property(device, "DeviceType", ".Device")
if device_type not in supported_device_types:
continue
- interfaces.append(proxy.get_cached_property("Interface").unpack())
+ iface = _get_property(device, "Interface", ".Device")
+ interfaces.append(iface)
return interfaces
@@ -120,19 +137,15 @@ def nm_activated_devices():
interfaces = []
- proxy = _get_proxy()
- active_connections = proxy.get_cached_property("ActiveConnections").unpack()
+ active_connections = _get_property("/org/freedesktop/NetworkManager", "ActiveConnections")
for ac in active_connections:
- proxy = _get_proxy(object_path=ac, interface_name="org.freedesktop.NetworkManager.Connection.Active")
- state = proxy.get_cached_property("State")
- if not state or state.unpack() != NetworkManager.ActiveConnectionState.ACTIVATED:
- continue
- devices = proxy.get_cached_property("Devices")
- if not devices:
+ state = _get_property(ac, "State", ".Connection.Active")
+ if state != NetworkManager.ActiveConnectionState.ACTIVATED:
continue
- for device in devices.unpack():
- proxy = _get_proxy(object_path=device, interface_name="org.freedesktop.NetworkManager.Device")
- interfaces.append(proxy.get_cached_property("Interface").unpack())
+ devices = _get_property(ac, "Devices", ".Connection.Active")
+ for device in devices:
+ iface = _get_property(device, "Interface", ".Device")
+ interfaces.append(iface)
return interfaces
@@ -181,18 +194,14 @@ def nm_device_property(name, prop):
raise
device = device.unpack()[0]
- proxy = _get_proxy(object_path=device, interface_name="org.freedesktop.NetworkManager.Device")
- if prop in proxy.get_cached_property_names():
- retval = proxy.get_cached_property(prop).unpack()
- else:
+ retval = _get_property(device, prop, ".Device")
+ if not retval:
# Look in device type based interface
interface = _device_type_specific_interface(device)
if interface:
- proxy = _get_proxy(object_path=device, interface_name=interface)
- if prop in proxy.get_cached_property_names():
- retval = proxy.get_cached_property(prop).unpack()
- else:
+ retval = _get_property(device, prop, interface[30:])
+ if not retval:
raise PropertyNotFoundError(prop)
else:
raise PropertyNotFoundError(prop)
@@ -284,10 +293,10 @@ def nm_device_ip_config(name, version=4):
return []
if version == 4:
- dbus_iface = "org.freedesktop.NetworkManager.IP4Config"
+ dbus_iface = ".IP4Config"
prop= "Ip4Config"
elif version == 6:
- dbus_iface = "org.freedesktop.NetworkManager.IP6Config"
+ dbus_iface = ".IP6Config"
prop= "Ip6Config"
else:
return []
@@ -296,9 +305,7 @@ def nm_device_ip_config(name, version=4):
if config == "/":
return []
- proxy = _get_proxy(object_path=config, interface_name=dbus_iface)
-
- addresses = proxy.get_cached_property("Addresses").unpack()
+ addresses = _get_property(config, "Addresses", dbus_iface)
addr_list = []
for addr, prefix, gateway in addresses:
# TODO - look for a library function (could have used IPy but byte order!)
@@ -310,7 +317,7 @@ def nm_device_ip_config(name, version=4):
gateway_str = nm_dbus_ay_to_ipv6(gateway)
addr_list.append([addr_str, prefix, gateway_str])
- nameservers = proxy.get_cached_property("Nameservers").unpack()
+ nameservers = _get_property(config, "Nameservers", dbus_iface)
ns_list = []
for ns in nameservers:
# TODO - look for a library function
@@ -322,7 +329,6 @@ def nm_device_ip_config(name, version=4):
return [addr_list, ns_list]
-
def nm_ntp_servers_from_dhcp():
"""Return a list of NTP servers that were specified the reply of the
DHCP server or empty list if no NTP servers were returned.
@@ -335,16 +341,15 @@ def nm_ntp_servers_from_dhcp():
for device in active_devices:
# harvest NTP server addresses from DHCPv4
dhcp4_path = nm_device_property(device, "Dhcp4Config")
- dhcp4_proxy = _get_proxy(object_path=dhcp4_path,
- interface_name="org.freedesktop.NetworkManager.DHCP4Config")
- options = dhcp4_proxy.get_cached_property("Options")
- if options and 'ntp_servers' in options.unpack():
+ options = _get_property(dhcp4_path, "Options", ".DHCP4Config")
+ if options and 'ntp_servers' in options:
# NTP server addresses returned by DHCP are whitespace delimited
- ntp_servers_string = options.unpack()["ntp_servers"]
+ ntp_servers_string = options["ntp_servers"]
for ip in ntp_servers_string.split(" "):
ntp_servers.append(ip)
# NetworkManager does not request NTP/SNTP options for DHCP6
+ print ntp_servers
return ntp_servers
def _device_settings(name):
diff --git a/pyanaconda/ui/gui/spokes/network.py b/pyanaconda/ui/gui/spokes/network.py
index f7c1275..132c7f2 100644
--- a/pyanaconda/ui/gui/spokes/network.py
+++ b/pyanaconda/ui/gui/spokes/network.py
@@ -43,7 +43,7 @@ from pyanaconda.ui.gui.utils import gtk_call_once, enlightbox
from pyanaconda.ui.common import FirstbootSpokeMixIn
from pyanaconda import network
-from pyanaconda.nm import nm_activated_devices, nm_device_setting_value, nm_dbus_ay_to_ipv6
+from pyanaconda.nm import nm_device_setting_value, nm_device_ip_config
from gi.repository import GLib, GObject, Pango, Gio, NetworkManager, NMClient
import dbus
@@ -704,12 +704,9 @@ class NetworkControlBox(object):
self._refresh_parent_vlanid(device)
self._refresh_speed_hwaddr(device, state)
self._refresh_ap(device, state)
- self._refresh_device_cfg(device, state)
+ self._refresh_device_cfg(device)
- def _refresh_device_cfg(self, device, state):
-
- if state is None:
- state = device.get_state()
+ def _refresh_device_cfg(self, device):
dev_type = device.get_device_type()
if dev_type == NetworkManager.DeviceType.ETHERNET:
@@ -721,45 +718,28 @@ class NetworkControlBox(object):
elif dev_type == NetworkManager.DeviceType.VLAN:
dt = "wired"
- if state == NetworkManager.DeviceState.ACTIVATED:
- ipv4cfg = device.get_ip4_config()
- ipv6cfg = device.get_ip6_config()
- else:
- ipv4cfg = None
- ipv6cfg = None
-
- if ipv4cfg:
- addr = socket.inet_ntoa(struct.pack('=L',
- ipv4cfg.get_addresses()[0].get_address()))
- self._set_device_info_value(dt, "ipv4", addr)
- dnss = " ".join(socket.inet_ntoa(struct.pack('=L', addr))
- for addr in ipv4cfg.get_nameservers())
- self._set_device_info_value(dt, "dns", dnss)
- gateway = socket.inet_ntoa(struct.pack('=L',
- ipv4cfg.get_addresses()[0].get_gateway()))
- self._set_device_info_value(dt, "route", gateway)
- if dt == "wired":
- prefix = ipv4cfg.get_addresses()[0].get_prefix()
- nm_utils.nm_utils_ip4_prefix_to_netmask.argtypes = [ctypes.c_uint32]
- nm_utils.nm_utils_ip4_prefix_to_netmask.restype = ctypes.c_uint32
- netmask = nm_utils.nm_utils_ip4_prefix_to_netmask(prefix)
- netmask = socket.inet_ntoa(struct.pack('=L', netmask))
- self._set_device_info_value(dt, "subnet", netmask)
+ ipv4cfg = nm_device_ip_config(device.get_iface(), version=4)
+ ipv6cfg = nm_device_ip_config(device.get_iface(), version=6)
+
+ if ipv4cfg and ipv4cfg[0]:
+ addr_str, prefix, gateway_str = ipv4cfg[0][0]
+ netmask_str = network.prefix2netmask(prefix)
+ dnss_str = " ".join(ipv4cfg[1])
else:
- self._set_device_info_value(dt, "ipv4", None)
- self._set_device_info_value(dt, "dns", None)
- self._set_device_info_value(dt, "route", None)
- if dt == "wired":
- self._set_device_info_value(dt, "subnet", None)
+ addr_str = dnss_str = gateway_str = netmask_str = None
+ self._set_device_info_value(dt, "ipv4", addr_str)
+ self._set_device_info_value(dt, "dns", dnss_str)
+ self._set_device_info_value(dt, "route", gateway_str)
+ if dt == "wired":
+ self._set_device_info_value(dt, "subnet", netmask_str)
- # TODO NM_GI_BUGS - segfaults on get_addres(), get_prefix()
addr6_str = ""
- if ipv6cfg:
- config = dbus.SystemBus().get_object(NM_SERVICE, ipv6cfg.get_path())
- for addr, _prefix, _gw in getNMObjProperty(config, ".IP6Config", "Addresses"):
- ipv6_addr = nm_dbus_ay_to_ipv6(addr)
- if not ipv6_addr.startswith("fe80:"):
- addr6_str += "%s\n" % ipv6_addr
+ if ipv6cfg and ipv6cfg[0]:
+ for ipv6addr in ipv6cfg[0]:
+ addr_str, prefix, gateway_str = ipv6addr
+ # Do not display link-local addresses
+ if not addr_str.startswith("fe80:"):
+ addr6_str += "%s/%d\n" % (addr_str, prefix)
self._set_device_info_value(dt, "ipv6", addr6_str.strip() or None)
--
1.7.11.7
10 years, 8 months
[master] Problematic patch I'm not sure we want to apply
by Vratislav Podzimek
This patch adds one more step to LiveCD installations -- generating new initrd
after the installation. With the DracutHostOnly feature [1] dracut now includes
only one keymap to the initrd image which makes the vconsole.keymap boot option
not working. Users need the keymap they used in the installation in the initrd,
especially when they use LUKS.
However, to save 3 MB (summed size of all keymaps) in the initrd size, all live
installations would generate initrd twice -- when the kernel package is
installed and at the end of the installation.
Vratislav Podzimek (1):
Regenerate initrd on live installations (#994180)
pyanaconda/install.py | 19 +++++++++++++++----
pyanaconda/iutil.py | 5 +++++
2 files changed, 20 insertions(+), 4 deletions(-)
--
1.7.11.7
10 years, 8 months
[blivet][rhel7-branch]
by David Lehman
These are all pretty simple patches that fix bugs. Patch 3 is
BS but we've supported it in the past so we're stuck with it.
10 years, 8 months
[PATCH] Don't set "date of last password change" /etc/shadow field (#985572)
by Vratislav Podzimek
From: Hans de Goede <hdegoede(a)redhat.com>
Signed-off-by: Vratislav Podzimek <vpodzime(a)redhat.com>
---
pyanaconda/users.py | 3 +++
1 file changed, 3 insertions(+)
diff --git a/pyanaconda/users.py b/pyanaconda/users.py
index ba5427a..e831122 100644
--- a/pyanaconda/users.py
+++ b/pyanaconda/users.py
@@ -335,6 +335,8 @@ class Users:
else:
password = cryptPassword(kwargs["password"], algo=kwargs.get("algo", None))
self.admin.setpassUser(userEnt, password, True)
+ userEnt.set(libuser.SHADOWLASTCHANGE, "")
+ self.admin.modifyUser(userEnt)
elif pw == "":
# Setup the account with *NO* password
self.admin.unlockUser(userEnt)
@@ -410,6 +412,7 @@ class Users:
if lock:
self.admin.lockUser(user)
+ user.set(libuser.SHADOWLASTCHANGE, "")
self.admin.modifyUser(user)
def setRootPassword(self, password, isCrypted=False, isLocked=False, algo=None):
--
1.7.11.7
10 years, 8 months
[master] Automake changes
by David Shea
Here's a handful of tweaks to the autotools files to (hopefully) make things
run a little more smoothly and to avoid having to keep track of files that we
don't have to.
The most immediately useful is patch 7, which changes the test scripts so that
they can be run from any working directory.
10 years, 8 months
[initial-setup][PATCH] Read /etc/system-release to get product title (#1000426)
by Vratislav Podzimek
The /etc/system-release file contains a release name that we want to display in
the UI.
For GUI we can use just the product title because the string "INITIAL SETUP" is
shown in the top-left corner. For TUI we should inform user that this is an
initial setup of the system.
Also rename the hub files not to clash with the the Python package name.
Signed-off-by: Vratislav Podzimek <vpodzime(a)redhat.com>
---
initial_setup/gui/gui.py | 13 +++---
initial_setup/gui/hubs/__init__.py | 2 +-
initial_setup/gui/hubs/initial_setup.py | 60 ----------------------------
initial_setup/gui/hubs/initial_setup_hub.py | 60 ++++++++++++++++++++++++++++
initial_setup/product.py | 31 +++++++++++++++
initial_setup/tui/hubs/__init__.py | 2 +-
initial_setup/tui/hubs/initial_setup.py | 55 --------------------------
initial_setup/tui/hubs/initial_setup_hub.py | 61 +++++++++++++++++++++++++++++
initial_setup/tui/tui.py | 13 +++---
9 files changed, 164 insertions(+), 133 deletions(-)
delete mode 100644 initial_setup/gui/hubs/initial_setup.py
create mode 100644 initial_setup/gui/hubs/initial_setup_hub.py
create mode 100644 initial_setup/product.py
delete mode 100644 initial_setup/tui/hubs/initial_setup.py
create mode 100644 initial_setup/tui/hubs/initial_setup_hub.py
diff --git a/initial_setup/gui/gui.py b/initial_setup/gui/gui.py
index 24e5a27..3afe5da 100644
--- a/initial_setup/gui/gui.py
+++ b/initial_setup/gui/gui.py
@@ -1,5 +1,5 @@
from pyanaconda.ui.gui import QuitDialog, GUIObject, GraphicalUserInterface
-#from .product import productName, productVersion
+from initial_setup.product import product_title, is_final
from .hubs import InitialSetupMainHub
from pyanaconda.ui.gui.spokes import StandaloneSpoke
import pyanaconda.ui.gui.spokes
@@ -13,27 +13,24 @@ from di import inject, usesclassinject
_ = lambda t: t
N_ = lambda t: t
-productTitle = lambda: "Initial Setup of Fedora"
-isFinal = lambda: False
-
class InitialSetupQuitDialog(QuitDialog):
MESSAGE = N_("Are you sure you want to quit the configuration process?\n"
"You might end up with unusable system if you do.")
-@inject(Gdk, productTitle = productTitle, isFinal = isFinal)
+@inject(Gdk, product_title = product_title, is_final = is_final)
class InitialSetupGraphicalUserInterface(GraphicalUserInterface):
"""This is the main Gtk based firstboot interface. It inherits from
anaconda to make the look & feel as similar as possible.
"""
screenshots_directory = "/tmp/initial-setup-screenshots"
-
+
@usesclassinject
def __init__(self, storage, payload, instclass):
GraphicalUserInterface.__init__(self, storage, payload, instclass,
- productTitle, isFinal,
+ product_title, is_final,
quitDialog = InitialSetupQuitDialog)
-
+
def _list_hubs(self):
return [InitialSetupMainHub]
diff --git a/initial_setup/gui/hubs/__init__.py b/initial_setup/gui/hubs/__init__.py
index 5d166d6..39d8b13 100644
--- a/initial_setup/gui/hubs/__init__.py
+++ b/initial_setup/gui/hubs/__init__.py
@@ -1 +1 @@
-from .initial_setup import InitialSetupMainHub
+from .initial_setup_hub import InitialSetupMainHub
diff --git a/initial_setup/gui/hubs/initial_setup.py b/initial_setup/gui/hubs/initial_setup.py
deleted file mode 100644
index f966782..0000000
--- a/initial_setup/gui/hubs/initial_setup.py
+++ /dev/null
@@ -1,60 +0,0 @@
-from pyanaconda.ui.gui.hubs import Hub
-from pyanaconda.ui.gui.spokes import Spoke
-from pyanaconda.ui.common import collect
-import os
-
-__all__ = ["InitialSetupMainHub"]
-
-def collect_spokes(mask_paths):
- """Return a list of all spoke subclasses that should appear for a given
- category. Look for them in files imported as module_path % basename(f)
-
- :param mask_paths: list of mask, path tuples to search for classes
- :type mask_paths: list of (mask, path)
-
- :return: list of Spoke classes belonging to category
- :rtype: list of Spoke classes
-
- """
- spokes = []
- for mask, path in mask_paths:
- spokes.extend(collect(mask, path,
- lambda obj: issubclass(obj, Spoke) and obj.should_run("firstboot", None)))
-
- print spokes
- return spokes
-
-
-class InitialSetupMainHub(Hub):
- uiFile = "initial_setup.glade"
- builderObjects = ["summaryWindow"]
- mainWidgetName = "summaryWindow"
-
- def _collectCategoriesAndSpokes(self):
- """collects categories and spokes to be displayed on this Hub
-
- :return: dictionary mapping category class to list of spoke classes
- :rtype: dictionary[category class] -> [ list of spoke classes ]
- """
-
- ret = {}
-
- # Collect all the categories this hub displays, then collect all the
- # spokes belonging to all those categories.
- candidate_spokes = collect_spokes(self.paths["spokes"])
- spokes = [spoke for spoke in candidate_spokes \
- if spoke.should_run("firstboot", self.data)]
-
- for spoke in spokes:
- ret.setdefault(spoke.category, [])
- ret[spoke.category].append(spoke)
-
- return ret
-
- @property
- def continueButton(self):
- return self.builder.get_object("continueButton")
-
- @property
- def quitButton(self):
- return self.builder.get_object("quitButton")
diff --git a/initial_setup/gui/hubs/initial_setup_hub.py b/initial_setup/gui/hubs/initial_setup_hub.py
new file mode 100644
index 0000000..d0ac15b
--- /dev/null
+++ b/initial_setup/gui/hubs/initial_setup_hub.py
@@ -0,0 +1,60 @@
+from pyanaconda.ui.gui.hubs import Hub
+from pyanaconda.ui.gui.spokes import Spoke
+from pyanaconda.ui.common import collect
+import os
+
+__all__ = ["InitialSetupMainHub"]
+
+def collect_spokes(mask_paths):
+ """Return a list of all spoke subclasses that should appear for a given
+ category. Look for them in files imported as module_path % basename(f)
+
+ :param mask_paths: list of mask, path tuples to search for classes
+ :type mask_paths: list of (mask, path)
+
+ :return: list of Spoke classes belonging to category
+ :rtype: list of Spoke classes
+
+ """
+ spokes = []
+ for mask, path in mask_paths:
+ spokes.extend(collect(mask, path,
+ lambda obj: issubclass(obj, Spoke) and obj.should_run("firstboot", None)))
+
+ print spokes
+ return spokes
+
+
+class InitialSetupMainHub(Hub):
+ uiFile = "initial_setup.glade"
+ builderObjects = ["summaryWindow"]
+ mainWidgetName = "summaryWindow"
+
+ def _collectCategoriesAndSpokes(self):
+ """collects categories and spokes to be displayed on this Hub
+
+ :return: dictionary mapping category class to list of spoke classes
+ :rtype: dictionary[category class] -> [ list of spoke classes ]
+ """
+
+ ret = {}
+
+ # Collect all the categories this hub displays, then collect all the
+ # spokes belonging to all those categories.
+ candidate_spokes = collect_spokes(self.paths["spokes"])
+ spokes = [spoke for spoke in candidate_spokes \
+ if spoke.should_run("firstboot", self.data)]
+
+ for spoke in spokes:
+ ret.setdefault(spoke.category, [])
+ ret[spoke.category].append(spoke)
+
+ return ret
+
+ @property
+ def continueButton(self):
+ return self.builder.get_object("continueButton")
+
+ @property
+ def quitButton(self):
+ return self.builder.get_object("quitButton")
diff --git a/initial_setup/product.py b/initial_setup/product.py
new file mode 100644
index 0000000..40cf45d
--- /dev/null
+++ b/initial_setup/product.py
@@ -0,0 +1,31 @@
+"""Module providing information about the installed product."""
+
+RELEASE_STRING_FILE = "/etc/system-release"
+
+def product_title():
+ """
+ Get product title.
+
+ :return: product title
+ :rtype: str
+
+ """
+
+ try:
+ with open(RELEASE_STRING_FILE, "r") as fobj:
+ title = fobj.readline().strip()
+
+ return title
+ except IOError:
+ return ""
+
+def is_final():
+ """
+ Whether it is a final release of the product or not.
+
+ :rtype: bool
+
+ """
+
+ # doesn't really matter for the Initial Setup
+ return True
diff --git a/initial_setup/tui/hubs/__init__.py b/initial_setup/tui/hubs/__init__.py
index 5d166d6..39d8b13 100644
--- a/initial_setup/tui/hubs/__init__.py
+++ b/initial_setup/tui/hubs/__init__.py
@@ -1 +1 @@
-from .initial_setup import InitialSetupMainHub
+from .initial_setup_hub import InitialSetupMainHub
diff --git a/initial_setup/tui/hubs/initial_setup.py b/initial_setup/tui/hubs/initial_setup.py
deleted file mode 100644
index a8521ad..0000000
--- a/initial_setup/tui/hubs/initial_setup.py
+++ /dev/null
@@ -1,55 +0,0 @@
-from pyanaconda.ui.tui.hubs import TUIHub
-from pyanaconda.ui.tui.spokes import TUISpoke
-from pyanaconda.ui.common import collect
-import os
-
-__all__ = ["InitialSetupMainHub"]
-
-# localization
-_ = lambda t: t
-N_ = lambda t: t
-
-def collect_spokes(mask_paths):
- """Return a list of all spoke subclasses that should appear for a given
- category. Look for them in files imported as module_path % basename(f)
-
- :param mask_paths: list of mask, path tuples to search for classes
- :type mask_paths: list of (mask, path)
-
- :return: list of Spoke classes belonging to category
- :rtype: list of Spoke classes
-
- """
- spokes = []
- for mask, path in mask_paths:
- spokes.extend(collect(mask, path,
- lambda obj: issubclass(obj, Spoke) and obj.should_run("firstboot", None)))
-
- print spokes
- return spokes
-
-
-class InitialSetupMainHub(TUIHub):
- categories = ["password", "localization"]
- title = _("Initial setup of Fedora")
-
- def _collectCategoriesAndSpokes(self):
- """collects categories and spokes to be displayed on this Hub
-
- :return: dictionary mapping category class to list of spoke classes
- :rtype: dictionary[category class] -> [ list of spoke classes ]
- """
-
- ret = {}
-
- # Collect all the categories this hub displays, then collect all the
- # spokes belonging to all those categories.
- candidate_spokes = collect_spokes(self.paths["spokes"])
- spokes = [spoke for spoke in candidate_spokes \
- if spoke.should_run("firstboot", self.data)]
-
- for spoke in spokes:
- ret.setdefault(spoke.category, [])
- ret[spoke.category].append(spoke)
-
- return ret
diff --git a/initial_setup/tui/hubs/initial_setup_hub.py b/initial_setup/tui/hubs/initial_setup_hub.py
new file mode 100644
index 0000000..6316179
--- /dev/null
+++ b/initial_setup/tui/hubs/initial_setup_hub.py
@@ -0,0 +1,61 @@
+from pyanaconda.ui.tui.hubs import TUIHub
+from pyanaconda.ui.tui.spokes import TUISpoke
+from pyanaconda.ui.common import collect
+from initial_setup import product
+import os
+
+__all__ = ["InitialSetupMainHub"]
+
+# localization
+_ = lambda t: t
+N_ = lambda t: t
+
+def collect_spokes(mask_paths):
+ """Return a list of all spoke subclasses that should appear for a given
+ category. Look for them in files imported as module_path % basename(f)
+
+ :param mask_paths: list of mask, path tuples to search for classes
+ :type mask_paths: list of (mask, path)
+
+ :return: list of Spoke classes belonging to category
+ :rtype: list of Spoke classes
+
+ """
+ spokes = []
+ for mask, path in mask_paths:
+ spokes.extend(collect(mask, path,
+ lambda obj: issubclass(obj, Spoke) and obj.should_run("firstboot", None)))
+
+ print spokes
+ return spokes
+
+
+class InitialSetupMainHub(TUIHub):
+ categories = ["password", "localization"]
+
+ prod_title = product.product_title()
+ if prod_title:
+ title = _("Initial setup of %(product)s") % {"product": prod_title}
+ else:
+ title = _("Initial setup")
+
+ def _collectCategoriesAndSpokes(self):
+ """collects categories and spokes to be displayed on this Hub
+
+ :return: dictionary mapping category class to list of spoke classes
+ :rtype: dictionary[category class] -> [ list of spoke classes ]
+ """
+
+ ret = {}
+
+ # Collect all the categories this hub displays, then collect all the
+ # spokes belonging to all those categories.
+ candidate_spokes = collect_spokes(self.paths["spokes"])
+ spokes = [spoke for spoke in candidate_spokes \
+ if spoke.should_run("firstboot", self.data)]
+
+ for spoke in spokes:
+ ret.setdefault(spoke.category, [])
+ ret[spoke.category].append(spoke)
+
+ return ret
diff --git a/initial_setup/tui/tui.py b/initial_setup/tui/tui.py
index 14b5af2..05cbd2c 100644
--- a/initial_setup/tui/tui.py
+++ b/initial_setup/tui/tui.py
@@ -1,5 +1,5 @@
from pyanaconda.ui.tui import TextUserInterface
-#from .product import productName, productVersion
+from initial_setup.product import product_title, is_final
from .hubs import InitialSetupMainHub
from pyanaconda.ui.tui.spokes import StandaloneSpoke
import pyanaconda.ui.tui.spokes
@@ -12,25 +12,22 @@ from di import inject, usesclassinject
_ = lambda t: t
N_ = lambda t: t
-productTitle = lambda: "Initial Setup of Fedora"
-isFinal = lambda: False
-
QUIT_MESSAGE = N_("Are you sure you want to quit the configuration process?\n"
"You might end up with unusable system if you do.")
-@inject(productTitle = productTitle, isFinal = isFinal)
+@inject(product_title = product_title, is_final = is_final)
class InitialSetupTextUserInterface(TextUserInterface):
"""This is the main text based firstboot interface. It inherits from
anaconda to make the look & feel as similar as possible.
"""
ENVIRONMENT = "firstboot"
-
+
@usesclassinject
def __init__(self, storage, payload, instclass):
TextUserInterface.__init__(self, storage, payload, instclass,
- productTitle, isFinal, quitMessage = QUIT_MESSAGE)
-
+ product_title, is_final, quitMessage = QUIT_MESSAGE)
+
def _list_hubs(self):
return [InitialSetupMainHub]
--
1.7.11.7
10 years, 8 months