[PATCH 1/7] Require passing the title to a Page's constructor.
by Chris Lumens
---
pyanaconda/ui/gui/spokes/custom.py | 14 ++++++--------
pyanaconda/ui/gui/spokes/lib/accordion.py | 12 ++++++------
2 files changed, 12 insertions(+), 14 deletions(-)
diff --git a/pyanaconda/ui/gui/spokes/custom.py b/pyanaconda/ui/gui/spokes/custom.py
index ba93b72..bb72697 100644
--- a/pyanaconda/ui/gui/spokes/custom.py
+++ b/pyanaconda/ui/gui/spokes/custom.py
@@ -684,8 +684,9 @@ class CustomPartitioningSpoke(NormalSpoke, StorageChecker):
# If we've not yet run autopart, add an instance of CreateNewPage. This
# ensures it's only added once.
if not new_devices:
- page = CreateNewPage(self.on_create_clicked, partitionsToReuse=bool(ui_roots))
- page.pageTitle = self.translated_new_install_name
+ page = CreateNewPage(self.translated_new_install_name,
+ self.on_create_clicked,
+ partitionsToReuse=bool(ui_roots))
self._accordion.addPage(page, cb=self.on_page_clicked)
if page.pageTitle not in page_order:
@@ -715,8 +716,7 @@ class CustomPartitioningSpoke(NormalSpoke, StorageChecker):
(root.name == self.translated_new_install_name or d.format.exists)]:
continue
- page = Page()
- page.pageTitle = root.name
+ page = Page(root.name)
for (mountpoint, device) in root.mounts.iteritems():
if device not in self._devices or \
@@ -744,8 +744,7 @@ class CustomPartitioningSpoke(NormalSpoke, StorageChecker):
# Anything that doesn't go with an OS we understand? Put it in the Other box.
if self.unusedDevices:
- page = UnknownPage()
- page.pageTitle = _("Unknown")
+ page = UnknownPage(_("Unknown"))
for u in sorted(self.unusedDevices, key=lambda d: d.name):
page.addSelector(u, self.on_selector_clicked)
@@ -803,8 +802,7 @@ class CustomPartitioningSpoke(NormalSpoke, StorageChecker):
expander = self._accordion._find_by_title(self.translated_new_install_name)
expander.remove(expander.get_child())
- page = Page()
- page.pageTitle = self.translated_new_install_name
+ page = Page(self.translated_new_install_name)
expander.add(page)
# pull in all the existing swap devices
diff --git a/pyanaconda/ui/gui/spokes/lib/accordion.py b/pyanaconda/ui/gui/spokes/lib/accordion.py
index 7c47c6a..d0d1a83 100644
--- a/pyanaconda/ui/gui/spokes/lib/accordion.py
+++ b/pyanaconda/ui/gui/spokes/lib/accordion.py
@@ -181,7 +181,7 @@ class Accordion(Gtk.Box):
# comprise a single installed OS into two categories - Data filesystems and System filesystems.
# Each filesystem is described by a single MountpointSelector.
class Page(Gtk.Box):
- def __init__(self):
+ def __init__(self, title):
Gtk.Box.__init__(self, orientation=Gtk.Orientation.VERTICAL, spacing=6)
# Create the Data label and a box to store all its members in.
@@ -195,7 +195,7 @@ class Page(Gtk.Box):
self.add(self._systemBox)
self._members = []
- self.pageTitle = ""
+ self.pageTitle = title
def _make_category_label(self, name):
label = Gtk.Label()
@@ -250,11 +250,11 @@ class Page(Gtk.Box):
cb(selector)
class UnknownPage(Page):
- def __init__(self):
+ def __init__(self, title):
# For this type of page, there's only one place to store members.
Gtk.Box.__init__(self, orientation=Gtk.Orientation.VERTICAL, spacing=6)
self._members = []
- self.pageTitle = ""
+ self.pageTitle = title
def addSelector(self, device, cb, mountpoint=""):
selector = selectorFromDevice(device, mountpoint=mountpoint)
@@ -275,9 +275,9 @@ class UnknownPage(Page):
# of this class will be packed into the Accordion first and then when the new installation
# is created, it will be removed and replaced with a Page for it.
class CreateNewPage(Page):
- def __init__(self, cb, partitionsToReuse=True):
+ def __init__(self, title, cb, partitionsToReuse=True):
Gtk.Box.__init__(self, orientation=Gtk.Orientation.VERTICAL, spacing=6)
- self.pageTitle = ""
+ self.pageTitle = title
# Create a box where we store the "Here's how you create a new blah" info.
self._createBox = Gtk.Grid()
--
1.8.1.2
11 years, 2 months
[PATCH 1/2] Don't display "(null)" as a MountpointSelector's mountpoint.
by Chris Lumens
---
pyanaconda/ui/gui/spokes/lib/accordion.py | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/pyanaconda/ui/gui/spokes/lib/accordion.py b/pyanaconda/ui/gui/spokes/lib/accordion.py
index aab6712..7c47c6a 100644
--- a/pyanaconda/ui/gui/spokes/lib/accordion.py
+++ b/pyanaconda/ui/gui/spokes/lib/accordion.py
@@ -69,7 +69,10 @@ def selectorFromDevice(device, selector=None, mountpoint=""):
allows for specifying the mountpoint if it cannot be determined from
the device (like for a Root specifying an existing installation).
"""
- mp = mountpoint or getattr(device.format, "mountpoint", "")
+ if hasattr(device.format, "mountpoint") and device.format.mountpoint is not None:
+ mp = device.format.mountpoint
+ else:
+ mp = mountpoint
if device.format.type == "swap":
name = "Swap"
--
1.8.1.2
11 years, 2 months
[PATCH 1/5] Fix a traceback in verifying optical media on the source spoke.
by Chris Lumens
This was caused by 1821378de1aecbbf5806edcad34ee928f0892296, which changed what
was being stored in the DiskOverviews.
---
pyanaconda/ui/gui/spokes/source.py | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/pyanaconda/ui/gui/spokes/source.py b/pyanaconda/ui/gui/spokes/source.py
index 0b71e77..a6223f4 100644
--- a/pyanaconda/ui/gui/spokes/source.py
+++ b/pyanaconda/ui/gui/spokes/source.py
@@ -841,7 +841,7 @@ class SourceSpoke(NormalSpoke):
dev = None
for child in self._autodetectMediaBox.get_children():
if child.get_chosen():
- dev = child
+ dev = child.props.name
break
return dev
@@ -923,7 +923,7 @@ class SourceSpoke(NormalSpoke):
dialog = MediaCheckDialog(self.data)
with enlightbox(self.window, dialog.window):
- dialog.run(dev.path)
+ dialog.run("/dev/" + dev)
def on_protocol_changed(self, combo):
proxyButton = self.builder.get_object("proxyButton")
--
1.8.1.2
11 years, 2 months
[PATCH rhel7-branch] Set ONBOOT=yes for devices activated in installer (rhel policy) (#913850)
by Radek Vykydal
This is additional patch for rhel that fixes change of behaviour caused by
previous fix for #905918.
The fix from the 905918 deactivates default auto connections and sets ONBOOT=no
at the beginning of the install.
This additional patch deals with the case when auto connection is activated
later (in UI) but ONBOOT value is kept to "no" which is not in accord with our
present rhel policy to autoactivate (after reboot) devices activated during
installation.
---
pyanaconda/installclasses/rhel.py | 16 ++++++++++++++++
1 file changed, 16 insertions(+)
diff --git a/pyanaconda/installclasses/rhel.py b/pyanaconda/installclasses/rhel.py
index d5b000e..8670106 100644
--- a/pyanaconda/installclasses/rhel.py
+++ b/pyanaconda/installclasses/rhel.py
@@ -20,6 +20,9 @@
from pyanaconda.installclass import BaseInstallClass
from pyanaconda.constants import *
from pyanaconda.product import *
+from pyanaconda import network
+from pyanaconda import isys
+
import types
class InstallClass(BaseInstallClass):
@@ -98,5 +101,18 @@ class InstallClass(BaseInstallClass):
return oldMajor == newMajor
+ def setNetworkOnbootDefault(self, ksdata):
+ for devName in network.getActiveNetDevs():
+ if isys.isWirelessDevice(devName):
+ continue
+ dev = network.NetworkDevice(ROOT_PATH + network.netscriptsDir, devName)
+ dev.loadIfcfgFile()
+ dev.set(('ONBOOT', 'yes'))
+ dev.writeIfcfgFile()
+ for nd in ksdata.network.network:
+ if nd.device == dev.iface:
+ nd.onboot = True
+ break
+
def __init__(self):
BaseInstallClass.__init__(self)
--
1.7.11.7
11 years, 2 months
[master] Continue booting when checkisomd5 is aborted (#891551)
by Brian C. Lane
From: "Brian C. Lane" <bcl(a)redhat.com>
---
anaconda.spec.in | 3 ++-
dracut/anaconda-diskroot | 5 ++++-
2 files changed, 6 insertions(+), 2 deletions(-)
diff --git a/anaconda.spec.in b/anaconda.spec.in
index 85585f0..a6551b9 100644
--- a/anaconda.spec.in
+++ b/anaconda.spec.in
@@ -35,6 +35,7 @@ Source0: %{name}-%{version}.tar.bz2
%define pythonurlgrabberver 3.9.1-5
%define utillinuxver 2.15.1
%define dracutver 024-16
+%define isomd5sum 1.0.10
BuildRequires: audit-libs-devel
BuildRequires: gettext >= %{gettextver}
@@ -102,7 +103,7 @@ Requires: GConf2 >= %{gconfversion}
%ifarch s390 s390x
Requires: openssh
%endif
-Requires: isomd5sum
+Requires: isomd5sum >= %{isomd5sum}
Requires: yum-utils >= %{yumutilsver}
Requires: NetworkManager >= %{nmver}
Requires: nm-connection-editor
diff --git a/dracut/anaconda-diskroot b/dracut/anaconda-diskroot
index 21c8afe..2df6248 100755
--- a/dracut/anaconda-diskroot
+++ b/dracut/anaconda-diskroot
@@ -15,10 +15,13 @@ run_checkisomd5() {
if [ -n "$DRACUT_SYSTEMD" ]; then
p=$(str_replace "$livedev" "-" '\x2d')
systemctl start checkisomd5(a)${p}.service
+ status=$(systemctl -p ExecMainStatus show checkisomd5(a)${p}.service)
+ splitsep "=" "$status" ignore rc
else
checkisomd5 --verbose $livedev
+ rc=$?
fi
- if [ $? -ne 0 ]; then
+ if [ "$rc" == "1" ]; then
die "CD check failed!"
exit 1
fi
--
1.8.1.2
11 years, 2 months
[isomd5sum] Fix for gcc type-punned and sizeof pointer warnings.
by Brian C. Lane
From: "Brian C. Lane" <bcl(a)redhat.com>
Casting the unsigned char array to uint32 generates this warning when
building with gcc 4.8.0
---
md5.c | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/md5.c b/md5.c
index 111aa86..ca6bf50 100644
--- a/md5.c
+++ b/md5.c
@@ -151,13 +151,12 @@ void MD5_Final(unsigned char digest[16], struct MD5Context *ctx)
if (ctx->doByteReverse) byteReverse(ctx->in, 14);
/* Append length in bits and transform */
- ((uint32 *) ctx->in)[14] = ctx->bits[0];
- ((uint32 *) ctx->in)[15] = ctx->bits[1];
+ memcpy(ctx->in+56, ctx->bits, sizeof(ctx->bits));
MD5_Transform(ctx->buf, (uint32 *) ctx->in);
if (ctx->doByteReverse) byteReverse((unsigned char *) ctx->buf, 4);
memcpy(digest, ctx->buf, 16);
- memset(ctx, 0, sizeof(ctx)); /* In case it's sensitive */
+ memset(ctx, 0, sizeof(*ctx)); /* In case it's sensitive */
}
#ifndef ASM_MD5
--
1.8.1.2
11 years, 2 months
[PATCH 1/3] Add the User creation spoke including the Advanced dialog
by Martin Sivak
---
pyanaconda/ui/gui/spokes/advanced_user.glade | 429 +++++++++++++++++++++++++++
pyanaconda/ui/gui/spokes/password.py | 2 +-
pyanaconda/ui/gui/spokes/user.glade | 363 +++++++++++++++++++++++
pyanaconda/ui/gui/spokes/user.py | 421 ++++++++++++++++++++++++++
4 files changed, 1214 insertions(+), 1 deletion(-)
create mode 100644 pyanaconda/ui/gui/spokes/advanced_user.glade
create mode 100644 pyanaconda/ui/gui/spokes/user.glade
create mode 100644 pyanaconda/ui/gui/spokes/user.py
diff --git a/pyanaconda/ui/gui/spokes/advanced_user.glade b/pyanaconda/ui/gui/spokes/advanced_user.glade
new file mode 100644
index 0000000..ee71c86
--- /dev/null
+++ b/pyanaconda/ui/gui/spokes/advanced_user.glade
@@ -0,0 +1,429 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <!-- interface-requires gtk+ 3.0 -->
+ <object class="GtkDialog" id="advancedUserDialog">
+ <property name="can_focus">False</property>
+ <property name="border_width">5</property>
+ <property name="type_hint">dialog</property>
+ <child internal-child="vbox">
+ <object class="GtkBox" id="dialog-vbox1">
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">2</property>
+ <child internal-child="action_area">
+ <object class="GtkButtonBox" id="dialog-action_area1">
+ <property name="can_focus">False</property>
+ <property name="layout_style">end</property>
+ <child>
+ <object class="GtkButton" id="button2">
+ <property name="label">gtk-cancel</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use_stock">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="button1">
+ <property name="label" translatable="yes">Save Changes</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="pack_type">end</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="box1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="margin_right">16</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkLabel" id="label1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">ADVANCED USER CONFIGURATION</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ <attribute name="scale" value="100"/>
+ <attribute name="size" value="125"/>
+ </attributes>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="margin_top">8</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">Home Directory</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="box2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="margin_left">16</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkCheckButton" id="c_home">
+ <property name="label" translatable="yes">Create a home directory for this user.</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="margin_top">4</property>
+ <property name="xalign">0</property>
+ <property name="draw_indicator">True</property>
+ <signal name="toggled" handler="_checkboxes" swapped="no"/>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="box3">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="margin_left">42</property>
+ <property name="margin_top">3</property>
+ <child>
+ <object class="GtkLabel" id="l_home">
+ <property name="visible">True</property>
+ <property name="sensitive">False</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Home directory:</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="t_home">
+ <property name="visible">True</property>
+ <property name="sensitive">False</property>
+ <property name="can_focus">True</property>
+ <property name="margin_left">13</property>
+ <property name="invisible_char">●</property>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label4">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="margin_top">8</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">User and Group IDs</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkGrid" id="grid1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="margin_left">16</property>
+ <property name="margin_top">3</property>
+ <child>
+ <object class="GtkCheckButton" id="c_uid">
+ <property name="label" translatable="yes">Specify a user ID manually:</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="xalign">0</property>
+ <property name="draw_indicator">True</property>
+ <signal name="toggled" handler="_checkboxes" swapped="no"/>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="c_gid">
+ <property name="label" translatable="yes">Specify a group ID manually:</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="xalign">0</property>
+ <property name="draw_indicator">True</property>
+ <signal name="toggled" handler="_checkboxes" swapped="no"/>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkSpinButton" id="spin_uid">
+ <property name="visible">True</property>
+ <property name="sensitive">False</property>
+ <property name="can_focus">True</property>
+ <property name="margin_left">8</property>
+ <property name="invisible_char">●</property>
+ <property name="width_chars">5</property>
+ <property name="progress_pulse_step">0.0099999997764825821</property>
+ <property name="adjustment">uid</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">0</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkSpinButton" id="spin_gid">
+ <property name="visible">True</property>
+ <property name="sensitive">False</property>
+ <property name="can_focus">True</property>
+ <property name="margin_left">8</property>
+ <property name="invisible_char">●</property>
+ <property name="width_chars">5</property>
+ <property name="adjustment">gid</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">1</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">4</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label5">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="margin_top">8</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">Group Membership</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">5</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="box4">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="margin_left">16</property>
+ <property name="margin_top">3</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkLabel" id="label6">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">Add user to the following groups:</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="t_groups">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="margin_top">3</property>
+ <property name="invisible_char">●</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkGrid" id="grid2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="margin_top">3</property>
+ <child>
+ <object class="GtkLabel" id="label7">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="margin_left">5</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">wheel, my-team (1245), project-x (29935)</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">0</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label8">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="margin_left">5</property>
+ <property name="margin_top">3</property>
+ <property name="xalign">0</property>
+ <property name="yalign">0</property>
+ <property name="label" translatable="yes">You may input a comma-separated list of group names and group IDs here.
+Groups that do not already exist will be created; specify their GID in parentheses. </property>
+ <property name="wrap">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">1</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label9">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">Example:</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label10">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="margin_top">3</property>
+ <property name="xalign">1</property>
+ <property name="yalign">0</property>
+ <property name="label" translatable="yes">Tip:</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">6</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <action-widgets>
+ <action-widget response="2">button2</action-widget>
+ <action-widget response="1">button1</action-widget>
+ </action-widgets>
+ </object>
+ <object class="GtkAdjustment" id="gid">
+ <property name="lower">500</property>
+ <property name="upper">32535</property>
+ <property name="value">1000</property>
+ <property name="step_increment">1</property>
+ <property name="page_increment">10</property>
+ </object>
+ <object class="GtkAdjustment" id="uid">
+ <property name="lower">500</property>
+ <property name="upper">32535</property>
+ <property name="value">1000</property>
+ <property name="step_increment">1</property>
+ <property name="page_increment">10</property>
+ </object>
+</interface>
diff --git a/pyanaconda/ui/gui/spokes/password.py b/pyanaconda/ui/gui/spokes/password.py
index 6950472..441050e 100644
--- a/pyanaconda/ui/gui/spokes/password.py
+++ b/pyanaconda/ui/gui/spokes/password.py
@@ -85,7 +85,7 @@ class PasswordSpoke(FirstbootSpokeMixIn, NormalSpoke):
@property
def mandatory(self):
- return False
+ return not self.data.user.userList
def apply(self):
self.data.rootpw.password = cryptPassword(self._password)
diff --git a/pyanaconda/ui/gui/spokes/user.glade b/pyanaconda/ui/gui/spokes/user.glade
new file mode 100644
index 0000000..2a29231
--- /dev/null
+++ b/pyanaconda/ui/gui/spokes/user.glade
@@ -0,0 +1,363 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <!-- interface-requires gtk+ 3.0 -->
+ <!-- interface-requires AnacondaWidgets 1.0 -->
+ <object class="AnacondaSpokeWindow" id="userCreationWindow">
+ <property name="startup_id">filler</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="startup_id">filler</property>
+ <property name="window_name" translatable="yes">CREATE USER</property>
+ <signal name="button-clicked" handler="on_back_clicked" swapped="no"/>
+ <child internal-child="main_box">
+ <object class="GtkBox" id="AnacondaSpokeWindow-main_box1">
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">6</property>
+ <child internal-child="nav_box">
+ <object class="GtkEventBox" id="AnacondaSpokeWindow-nav_box1">
+ <property name="app_paintable">True</property>
+ <property name="can_focus">False</property>
+ <child internal-child="nav_area">
+ <object class="GtkGrid" id="AnacondaSpokeWindow-nav_area1">
+ <property name="can_focus">False</property>
+ <property name="margin_left">6</property>
+ <property name="margin_right">6</property>
+ <property name="margin_top">6</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child internal-child="alignment">
+ <object class="GtkAlignment" id="AnacondaSpokeWindow-alignment1">
+ <property name="can_focus">False</property>
+ <property name="margin_top">12</property>
+ <property name="yalign">0</property>
+ <property name="xscale">0.75</property>
+ <property name="yscale">0.75</property>
+ <property name="bottom_padding">48</property>
+ <property name="left_padding">24</property>
+ <property name="right_padding">24</property>
+ <child internal-child="action_area">
+ <object class="GtkBox" id="AnacondaSpokeWindow-action_area1">
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkGrid" id="grid1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="row_spacing">8</property>
+ <property name="column_spacing">9</property>
+ <child>
+ <object class="GtkLabel" id="label1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">1</property>
+ <property name="xpad">10</property>
+ <property name="label" translatable="yes">Full name</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">1</property>
+ <property name="xpad">10</property>
+ <property name="label" translatable="yes">Username</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="t_fullname">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="invisible_char">●</property>
+ <property name="invisible_char_set">True</property>
+ <property name="caps_lock_warning">False</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">0</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="t_username">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="invisible_char">●</property>
+ <property name="invisible_char_set">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">1</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label3">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">1</property>
+ <property name="xpad">10</property>
+ <property name="label" translatable="yes">Password</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">5</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label4">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">1</property>
+ <property name="xpad">10</property>
+ <property name="label" translatable="yes">Confirm password</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">7</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="t_password">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="visibility">False</property>
+ <property name="invisible_char">●</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">5</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="t_verifypassword">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="visibility">False</property>
+ <property name="invisible_char">●</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">7</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label6">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes"><b>Tip:</b> lorem ipsum dolor sit amet...</property>
+ <property name="use_markup">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">2</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="c_usepassword">
+ <property name="label" translatable="yes">Require a password to use this account</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="xalign">0</property>
+ <property name="active">True</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">4</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="box2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkLevelBar" id="password_bar">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">2</property>
+ <property name="mode">GTK_LEVEL_BAR_MODE_DISCRETE</property>
+ <property name="min-value">0</property>
+ <property name="max-value">4</property>
+ <property name="orientation">GTK_ORIENTATION_HORIZONTAL</property>
+ <property name="value">2</property>
+ <property name="halign">fill</property>
+ <property name="valign">center</property>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="password_label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="valign">center</property>
+ <property name="xpad">6</property>
+ <property name="label" translatable="yes">empty password</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">6</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="c_admin">
+ <property name="label" translatable="yes">Make this user administrator</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="xalign">0</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">3</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkGrid" id="grid2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkButton" id="b_advanced">
+ <property name="label" translatable="yes">Advanced...</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <signal name="clicked" handler="on_advanced_clicked" swapped="no"/>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="b_network_login">
+ <property name="label" translatable="yes">Use network login...</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="margin_left">6</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">0</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">8</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ </child>
+ </object>
+</interface>
diff --git a/pyanaconda/ui/gui/spokes/user.py b/pyanaconda/ui/gui/spokes/user.py
new file mode 100644
index 0000000..6655be6
--- /dev/null
+++ b/pyanaconda/ui/gui/spokes/user.py
@@ -0,0 +1,421 @@
+# User creation spoke
+#
+# Copyright (C) 2012 Red Hat, Inc.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions of
+# the GNU General Public License v.2, or (at your option) any later version.
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY expressed or implied, including the implied warranties of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+# Public License for more details. You should have received a copy of the
+# GNU General Public License along with this program; if not, write to the
+# Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+# 02110-1301, USA. Any Red Hat trademarks that are incorporated in the
+# source code or documentation are not subject to the GNU General Public
+# License and may only be used or replicated with the express permission of
+# Red Hat, Inc.
+#
+# Red Hat Author(s): Martin Sivak <msivak(a)redhat.com>
+#
+
+import gettext
+_ = lambda x: gettext.ldgettext("anaconda", x)
+N_ = lambda x: x
+
+from gi.repository import Gtk
+
+from pyanaconda.users import cryptPassword, validatePassword
+from pwquality import PWQError
+import string
+
+from pyanaconda.ui.gui.spokes import NormalSpoke
+from pyanaconda.ui.gui import GUIObject
+from pyanaconda.ui.gui.categories.user_settings import UserSettingsCategory
+from pyanaconda.ui.common import FirstbootSpokeMixIn
+from pyanaconda.ui.gui.utils import enlightbox
+
+import unicodedata
+import pwquality
+
+__all__ = ["UserSpoke", "AdvancedUserDialog"]
+
+def strip_accents(s):
+ """This function takes arbitrary unicode string
+ and returns it with all the diacritics removed.
+
+ :param s: arbitrary string
+ :type s: unicode
+
+ :return: s with diacritics removed
+ :rtype: unicode
+
+ """
+ return ''.join((c for c in unicodedata.normalize('NFD', s)
+ if unicodedata.category(c) != 'Mn'))
+
+class AdvancedUserDialog(GUIObject):
+ builderObjects = ["advancedUserDialog", "uid", "gid"]
+ mainWidgetName = "advancedUserDialog"
+ uiFile = "advanced_user.glade"
+
+ def __init__(self, user, groupDict, data):
+ GUIObject.__init__(self, data)
+ self._user = user
+ self._groupDict = groupDict
+
+ def initialize(self):
+ pass
+
+ def _checkboxes(self, _editable, data = None):
+ """Update the state of this screen according to the
+ checkbox states on the screen. It is called from
+ the toggled Gtk event.
+ """
+ c_home = self.builder.get_object("c_home").get_active()
+ c_uid = self.builder.get_object("c_uid").get_active()
+ c_gid = self.builder.get_object("c_gid").get_active()
+
+ self.builder.get_object("t_home").set_sensitive(c_home)
+ self.builder.get_object("l_home").set_sensitive(c_home)
+ self.builder.get_object("spin_uid").set_sensitive(c_uid)
+ self.builder.get_object("spin_gid").set_sensitive(c_gid)
+
+ def refresh(self):
+ t_home = self.builder.get_object("t_home")
+ if self._user.homedir:
+ t_home.set_text(self._user.homedir)
+ elif self._user.name:
+ t_home.set_text("/home/%s" % self._user.name)
+
+ groups = []
+ for group_name in self._user.groups:
+ group = self._groupDict[group_name]
+
+ if group.name and group.gid is not None:
+ groups.append("%s (%d)" % (group.name, group.gid))
+ elif group.name:
+ groups.append(group.name)
+ elif group.gid is not None:
+ groups.append("(%d)" % (group.gid,))
+
+ self.builder.get_object("t_groups").set_text(", ".join(groups))
+
+ def run(self):
+ self.window.show()
+ rc = self.window.run()
+ self.window.hide()
+
+ #OK clicked
+ if rc == 1:
+ if self.builder.get_object("c_home").get_active():
+ self._user.homedir = self.builder.get_object("t_home").get_text()
+ else:
+ self._user.homedir = None
+
+ if self.builder.get_object("c_uid").get_active():
+ self._user.uid = int(self.builder.get_object("uid").get_value())
+ else:
+ self._user.uid = None
+
+ if self.builder.get_object("c_gid").get_active():
+ pass
+ #self._user.gid = int(self.builder.get_widget("gid").get_value())
+ else:
+ #self._user.gid = None
+ pass
+
+ groups = self.builder.get_object("t_groups").get_text().split(",")
+ self._user.groups = []
+ for group in groups:
+ group = group.strip()
+ if group not in self._groupDict:
+ self._groupDict[group] = self.data.GroupData(name = group)
+ self._user.groups.append(group)
+
+ #Cancel clicked, window destroyed...
+ else:
+ pass
+
+ return rc
+
+
+
+class UserSpoke(FirstbootSpokeMixIn, NormalSpoke):
+ builderObjects = ["userCreationWindow"]
+
+ mainWidgetName = "userCreationWindow"
+ uiFile = "spokes/user.glade"
+
+ category = UserSettingsCategory
+
+ icon = "avatar-default-symbolic"
+ title = N_("_USER CREATION")
+
+ def __init__(self, *args):
+ NormalSpoke.__init__(self, *args)
+ self._oldweak = None
+ self._error = None
+
+ def initialize(self):
+ NormalSpoke.initialize(self)
+ self._user = self.data.UserData()
+ self._wheel = self.data.GroupData(name = "wheel")
+ self._groupDict = {"wheel": self._wheel}
+
+ # place holders for the text boxes
+ self.fullname = self.builder.get_object("t_fullname")
+ self.username = self.builder.get_object("t_username")
+ self.pw = self.builder.get_object("t_password")
+ self.confirm = self.builder.get_object("t_verifypassword")
+ self.admin = self.builder.get_object("c_admin")
+ self.usepassword = self.builder.get_object("c_usepassword")
+
+ self.guesser = {
+ self.username: True
+ }
+
+ self.pw.connect("changed", self._checkPassword)
+ self.confirm.connect("changed", self._checkPassword)
+ self.fullname.connect("changed", self._guessNames)
+ self.username.connect("changed", self._guessNameDisabler)
+ self.usepassword.connect("toggled", self._passwordDisabler)
+
+ # set up passphrase quality checker
+ self._pwq = pwquality.PWQSettings()
+ self._pwq.read_config()
+
+ self.pw_bar = self.builder.get_object("password_bar")
+ self.pw_label = self.builder.get_object("password_label")
+
+ self._advanced = AdvancedUserDialog(self._user, self._groupDict,
+ self.data)
+ self._advanced.initialize()
+
+ def refresh(self):
+ if self.usepassword.get_active():
+ self._checkPassword()
+
+ if self.username.get_text() and self.usepassword.get_active():
+ self.pw.grab_focus()
+ elif self.fullname.get_text():
+ self.username.grab_focus()
+ else:
+ self.fullname.grab_focus()
+
+ @property
+ def status(self):
+ if self._error:
+ return _("Error creating user account: %s") % self._error
+ elif len(self.data.user.userList) == 0:
+ return _("No user will be created")
+ elif self._wheel.name in self.data.user.userList[0].groups:
+ return _("Administrator %s will be created") % self.data.user.userList[0].name
+ else:
+ return _("User %s will be created") % self.data.user.userList[0].name
+
+ @property
+ def mandatory(self):
+ # mandatory only if root account is disabled
+ return (not self.data.rootpw.password) or self.data.rootpw.lock
+
+ def apply(self):
+ if self.username.get_text():
+ self._user.name = self.username.get_text()
+ self._user.password = cryptPassword(self.pw.get_text())
+ self._user.isCrypted = True
+
+ if self.admin.get_active() and \
+ self._wheel.name not in self._user.groups:
+ self._user.groups.append(self._wheel.name)
+ elif not self.admin.get_active() and \
+ self._wheel.name in self._user.groups:
+ self._user.groups.remove(self._wheel.name)
+
+ self.data.group.groupList += [self._groupDict[g] for g in self._user.groups
+ if g != self._wheel.name]
+
+ if self._user not in self.data.user.userList:
+ self.data.user.userList.append(self._user)
+
+ elif self._user in self.data.user.userList:
+ self.data.user.userList.remove(self._user)
+
+ @property
+ def completed(self):
+ return self._user in self.data.user.userList
+
+ def _passwordDisabler(self, editable = None, data = None):
+ """Called by Gtk callback when the "Use password" check
+ button is toggled. It will make password entries in/sensitive."""
+
+ self.pw.set_sensitive(self.usepassword.get_active())
+ self.confirm.set_sensitive(self.usepassword.get_active())
+ if not self.usepassword.get_active():
+ self.clear_info()
+ else:
+ self._checkPassword()
+
+ def _guessNameDisabler(self, editable = None, data = None):
+ """Called by Gtk callback when the username or hostname
+ entry changes. It disables the guess algorithm if the
+ user added his own text there and reenable it when the
+ user deletes the whole text."""
+
+ if editable.get_text() == "":
+ self.guesser[editable] = True
+ self._guessNames()
+ else:
+ self.guesser[editable] = False
+
+ def _guessNames(self, editable = None, data = None):
+ """Called by Gtk callback when the full name field changes.
+ It guesses the username and hostname, strips diacritics
+ and make those lowercase.
+ """
+
+ fullname = self.fullname.get_text().split()
+ username = fullname[-1].decode("utf-8").lower()
+ if len(fullname) > 1:
+ username = fullname[0][0].decode("utf-8").lower() + username
+ username = strip_accents(username).encode("utf-8")
+
+ # after the text is updated in guesser, the guess has to be reenabled
+ if self.guesser[self.username]:
+ self.username.set_text(username)
+ self.guesser[self.username] = True
+
+ def _checkPassword(self, editable = None, data = None):
+ """This method updates the password indicators according
+ to the passwords entered by the user. It is called by
+ the changed Gtk event handler.
+ """
+ if self.pw.get_text() == "":
+ strength = -2
+ elif self.pw.get_text() != self.confirm.get_text():
+ strength = -1
+ else:
+ try:
+ strength = self._pwq.check(self.pw.get_text(), None, None)
+ _pwq_error = None
+ except pwquality.PWQError as (e, msg):
+ _pwq_error = msg
+ strength = 0
+
+ if strength == -1:
+ val = 0
+ text = _("Mismatch!")
+ self._error = _("The passwords do not match!")
+ elif strength == -2:
+ val = 0
+ text = _("Empty!")
+ self._error = _("The password is empty!")
+ elif strength < 50:
+ val = 1
+ text = _("Weak")
+ self._error = _("The password you have provided is weak")
+ if _pwq_error:
+ self._error += ": %s. " % _pwq_error
+ else:
+ self._error += ". "
+ self._error += _("You will have to press Done twice to confirm it.")
+ elif strength < 75:
+ val = 2
+ text = _("Fair")
+ self._error = False
+ elif strength < 90:
+ val = 3
+ text = _("Good")
+ self._error = False
+ else:
+ val = 4
+ text = _("Strong")
+ self._error = False
+
+ self.pw_bar.set_value(val)
+ self.pw_label.set_text(text)
+
+ self.clear_info()
+ if self._error:
+ self.set_warning(self._error)
+ self.window.show_all()
+
+ def _validatePassword(self):
+ """This method checks the password weakness and
+ implements the Press Done twice logic. It is used from
+ the on_back_clicked handler.
+
+ It also sets the self._error of the password is not
+ sufficient or does not pass the pwquality checks.
+
+ :return: True if the password should be accepted, False otherwise
+ :rtype: bool
+
+ """
+
+ # Do various steps to validate the password
+ # sets self._error to an error string
+ # Return True if valid, False otherwise
+ self._error = False
+ pw = self.pw.get_text()
+ confirm = self.confirm.get_text()
+
+ if not pw and not confirm:
+ self._error = _("You must provide and confirm a password.")
+ return False
+
+ try:
+ self._error = validatePassword(pw, confirm)
+ except PWQError as (_e, msg):
+ if pw == self._oldweak:
+ # We got a second attempt with the same weak password
+ pass
+ else:
+ self._error = _("You have provided a weak password: %s. "
+ " Press Done again to use anyway.") % msg
+ self._oldweak = pw
+ return False
+
+ if self._error:
+ return False
+
+ # if no errors, clear the info for next time we go into the spoke
+ self._password = pw
+ self.clear_info()
+ self._error = False
+ return True
+
+ def on_advanced_clicked(self, _button):
+ """Handler for the Advanced.. button. It starts the Advanced dialog
+ for setting homedit, uid, gid and groups.
+ """
+
+ self._user.name = self.username.get_text()
+
+ if self.admin.get_active() and \
+ self._wheel.name not in self._user.groups:
+ self._user.groups.append(self._wheel.name)
+ elif not self.admin.get_active() and \
+ self._wheel.name in self._user.groups:
+ self._user.groups.remove(self._wheel.name)
+
+ self._advanced.refresh()
+ with enlightbox(self.window, self._advanced.window):
+ response = self._advanced.run()
+
+ if response == 1:
+ pass
+
+ self.admin.set_active(self._wheel.name in self._user.groups)
+
+ def on_back_clicked(self, button):
+ if not self.usepassword.get_active() or self._validatePassword():
+ self._error = False
+ self.clear_info()
+ NormalSpoke.on_back_clicked(self, button)
+ else:
+ self.clear_info()
+ self.set_warning(self._error)
+ self.pw.grab_focus()
+ self.window.show_all()
+
--
1.7.11.7
11 years, 2 months
[PATCH] dracut: add anaconda-pre-shutdown.sh to fix eject (#809920)
by Will Woods
So it turns out that having the device that contains the runtime image
mounted *underneath* the runtime image means we have a mount loop, e.g.:
The DVD can't be unmounted because it holds the image for /
/ can't be unmounted because the DVD is mounted underneath it
To fix this, we move the repo mount(s) back out from under the runtime
image during dracut's pre-shutdown hook (new in dracut 025).
---
anaconda.spec.in | 2 +-
dracut/Makefile.am | 3 ++-
dracut/anaconda-pre-shutdown.sh | 20 ++++++++++++++++++++
dracut/module-setup.sh | 1 +
4 files changed, 24 insertions(+), 2 deletions(-)
create mode 100644 dracut/anaconda-pre-shutdown.sh
diff --git a/anaconda.spec.in b/anaconda.spec.in
index 85585f0..57a4c7c 100644
--- a/anaconda.spec.in
+++ b/anaconda.spec.in
@@ -34,7 +34,7 @@ Source0: %{name}-%{version}.tar.bz2
%define firewalldver 0.2.9-1
%define pythonurlgrabberver 3.9.1-5
%define utillinuxver 2.15.1
-%define dracutver 024-16
+%define dracutver 025
BuildRequires: audit-libs-devel
BuildRequires: gettext >= %{gettextver}
diff --git a/dracut/Makefile.am b/dracut/Makefile.am
index 7646e23..53a30cb 100644
--- a/dracut/Makefile.am
+++ b/dracut/Makefile.am
@@ -39,7 +39,8 @@ dist_dracut_SCRIPTS = module-setup.sh \
fetch-updates-disk \
parse-kickstart \
anaconda-modprobe.sh \
- save-initramfs.sh
+ save-initramfs.sh \
+ anaconda-pre-shutdown.sh
MAINTAINERCLEANFILES = Makefile.in
diff --git a/dracut/anaconda-pre-shutdown.sh b/dracut/anaconda-pre-shutdown.sh
new file mode 100644
index 0000000..78f9f06
--- /dev/null
+++ b/dracut/anaconda-pre-shutdown.sh
@@ -0,0 +1,20 @@
+# Fix mount loops that prevent unmount/eject.
+#
+# During startup, we mount our repo (e.g. the DVD) at $repodir or $isodir.
+# We then mount the runtime image from that repo at /newroot and switch into it.
+# Switching moves $repodir to /newroot/$repodir, which creates a mount loop:
+#
+# -> You can't unmount the runtime image because the DVD is mounted under it
+# -> You can't unmount the DVD because it holds the mounted runtime image
+#
+# And now you can't unmount or eject the DVD!
+#
+# We fix this by moving the repo mounts back out from under the runtime image
+# during shutdown. Then everything can be unmounted like normal.
+
+. /lib/anaconda-lib.sh
+
+for mnt in $repodir $isodir; do
+ oldmnt=/oldroot$mnt
+ grep -qw $oldmnt /proc/mounts && mount --move $oldmnt $mnt
+done
diff --git a/dracut/module-setup.sh b/dracut/module-setup.sh
index b9997f8..bc917e5 100755
--- a/dracut/module-setup.sh
+++ b/dracut/module-setup.sh
@@ -34,6 +34,7 @@ install() {
inst_hook pre-pivot 50 "$moddir/anaconda-copy-ks.sh"
inst_hook pre-pivot 50 "$moddir/anaconda-copy-cmdline.sh"
inst_hook pre-pivot 99 "$moddir/save-initramfs.sh"
+ inst_hook pre-shutdown 50 "$moddir/anaconda-pre-shutdown.sh"
# kickstart parsing, WOOOO
inst_hook initqueue/online 10 "$moddir/fetch-kickstart-net.sh"
inst "$moddir/fetch-kickstart-disk" "/sbin/fetch-kickstart-disk"
--
1.8.1.2
11 years, 2 months
[PATCH] remove sparc support
by Dennis Gilmore
Signed-off-by: Dennis Gilmore <dennis(a)ausil.us>
---
lorax.spec | 4 ----
share/live/sparc.tmpl | 38 --------------------------------------
share/runtime-install.tmpl | 3 ---
share/sparc.tmpl | 38 --------------------------------------
src/pylorax/__init__.py | 3 +--
src/pylorax/treebuilder.py | 2 --
6 files changed, 1 insertion(+), 87 deletions(-)
delete mode 100644 share/live/sparc.tmpl
delete mode 100644 share/sparc.tmpl
diff --git a/lorax.spec b/lorax.spec
index 22a50d2..013d0a8 100644
--- a/lorax.spec
+++ b/lorax.spec
@@ -45,10 +45,6 @@ Requires: fedup-dracut-plymouth
Requires: syslinux >= 4.02-5
%endif
-%ifarch %{sparc}
-Requires: silo
-%endif
-
%ifarch ppc ppc64
Requires: kernel-bootwrapper
%endif
diff --git a/share/live/sparc.tmpl b/share/live/sparc.tmpl
deleted file mode 100644
index 2452f80..0000000
--- a/share/live/sparc.tmpl
+++ /dev/null
@@ -1,38 +0,0 @@
-<%page args="kernels, runtime_img, basearch, outroot, product, isolabel"/>
-<%
-configdir="tmp/config_files/sparc"
-BOOTDIR="boot"
-LIVEDIR="LiveOS"
-%>
-
-mkdir ${LIVEDIR}
-install ${runtime_img} ${LIVEDIR}/squashfs.img
-treeinfo stage2 mainimage ${LIVEDIR}/squashfs.img
-
-## install bootloader and config files
-install boot/*.b ${BOOTDIR}
-install ${configdir}/silo.conf ${BOOTDIR}
-install ${configdir}/boot.msg ${BOOTDIR}
-
-## configure bootloader
-replace @VERSION@ ${product.version} ${BOOTDIR}/boot.msg
-replace @PRODUCT@ '${product.name}' ${BOOTDIR}/boot.msg
-replace @ROOT@ 'root=live:CDLABEL=${isolabel|udev}' ${BOOTDIR}/silo.conf
-
-## install kernels
-## FIXME: this will overwrite if there are multiple sparc kernels
-%for kernel in kernels:
- installkernel images-${basearch} ${kernel.path} ${BOOTDIR}/vmlinuz
- installinitrd images-${basearch} ${kernel.initrd.path} ${BOOTDIR}/initrd.img
-%endfor
-
-## make boot.iso
-runcmd mkisofs -R -J -T -G /${BOOTDIR}/isofs.b -B ... \
- -s /${BOOTDIR}/silo.conf -r -V '${isolabel}' \
- -A "${product.name} ${product.version}" \
- -x Fedora -x repodata \
- -sparc-label "${product.name} ${product.version} Boot Disc" \
- -o ${outroot}/images/boot.iso \
- -graft-points ${BOOTDIR}=${outroot}/${BOOTDIR} \
- ${LIVEDIR}=${outroot}/${LIVEDIR}
-treeinfo images-${basearch} boot.iso images/boot.iso
diff --git a/share/runtime-install.tmpl b/share/runtime-install.tmpl
index e4cfebd..686fb0d 100644
--- a/share/runtime-install.tmpl
+++ b/share/runtime-install.tmpl
@@ -37,9 +37,6 @@ installpkg kernel
%if basearch == "s390x":
installpkg lsscsi modutils s390utils-base s390utils-cmsfs-fuse
%endif
-%if basearch == "sparc":
- installpkg silo tilo
-%endif
## yay, plymouth
installpkg plymouth
diff --git a/share/sparc.tmpl b/share/sparc.tmpl
deleted file mode 100644
index 1a66e2c..0000000
--- a/share/sparc.tmpl
+++ /dev/null
@@ -1,38 +0,0 @@
-<%page args="kernels, runtime_img, basearch, outroot, product, isolabel"/>
-<%
-configdir="tmp/config_files/sparc"
-BOOTDIR="boot"
-LIVEDIR="LiveOS"
-%>
-
-mkdir ${LIVEDIR}
-install ${runtime_img} ${LIVEDIR}/squashfs.img
-treeinfo stage2 mainimage ${LIVEDIR}/squashfs.img
-
-## install bootloader and config files
-install boot/*.b ${BOOTDIR}
-install ${configdir}/silo.conf ${BOOTDIR}
-install ${configdir}/boot.msg ${BOOTDIR}
-
-## configure bootloader
-replace @VERSION@ ${product.version} ${BOOTDIR}/boot.msg
-replace @PRODUCT@ '${product.name}' ${BOOTDIR}/boot.msg
-replace @ROOT@ 'inst.stage2=hd:LABEL=${isolabel|udev}' ${BOOTDIR}/silo.conf
-
-## install kernels
-## FIXME: this will overwrite if there are multiple sparc kernels
-%for kernel in kernels:
- installkernel images-${basearch} ${kernel.path} ${BOOTDIR}/vmlinuz
- installinitrd images-${basearch} ${kernel.initrd.path} ${BOOTDIR}/initrd.img
-%endfor
-
-## make boot.iso
-runcmd mkisofs -R -J -T -G /${BOOTDIR}/isofs.b -B ... \
- -s /${BOOTDIR}/silo.conf -r -V '${isolabel}' \
- -A "${product.name} ${product.version}" \
- -x Fedora -x repodata \
- -sparc-label "${product.name} ${product.version} Boot Disc" \
- -o ${outroot}/images/boot.iso \
- -graft-points ${BOOTDIR}=${outroot}/${BOOTDIR} \
- ${LIVEDIR}=${outroot}/${LIVEDIR}
-treeinfo images-${basearch} boot.iso images/boot.iso
diff --git a/src/pylorax/__init__.py b/src/pylorax/__init__.py
index 3eff6e8..069628e 100644
--- a/src/pylorax/__init__.py
+++ b/src/pylorax/__init__.py
@@ -50,10 +50,9 @@ from discinfo import DiscInfo
from executils import runcmd, runcmd_output
class ArchData(DataHolder):
- lib64_arches = ("x86_64", "ppc64", "sparc64", "s390x", "ia64")
+ lib64_arches = ("x86_64", "ppc64", "s390x", "ia64")
bcj_arch = dict(i386="x86", x86_64="x86",
ppc="powerpc", ppc64="powerpc",
- sparc="sparc", sparc64="sparc",
arm="arm", armhfp="arm")
def __init__(self, buildarch):
diff --git a/src/pylorax/treebuilder.py b/src/pylorax/treebuilder.py
index acd1a59..37f10ec 100644
--- a/src/pylorax/treebuilder.py
+++ b/src/pylorax/treebuilder.py
@@ -35,8 +35,6 @@ templatemap = {
'x86_64': 'x86.tmpl',
'ppc': 'ppc.tmpl',
'ppc64': 'ppc.tmpl',
- 'sparc': 'sparc.tmpl',
- 'sparc64': 'sparc.tmpl',
's390': 's390.tmpl',
's390x': 's390.tmpl',
'arm': 'arm.tmpl',
--
1.8.1.4
11 years, 2 months
[PATCH anaconda-dracut] Fix ksdevice=<MAC> - instead of renaming the device to ksdev0 just use it
by Radek Vykydal
ksdevice option doesn't work in f17 and f18.
It used to specify which network device to activate in early stage of
installation, eg. to fetch kickstart or installation image.
In F17 and F18 the device should be specified by dracut option ip=
Mapping of ksdevice options from loader to dracut options used in
F17 and F18:
- ksdevice missing (and network is required)
loader: user was asked in UI in case of more devices present
dracut: activates all devices if not specified
- ksdevice=eth0
loader: eth0 is activated
dracut: specify device in ip=, eg
ip=eth0:dhcp
ip=10.34.39.44::10.34.39.254:255.255.255.0::eth0:none
- ksdevice=00:12:34:56:78:9a
loader: device with MAC address is activated
dracut: We translate it to ifname=ksdev0:00:12:34:56:78:9a which renames
the device.
It is possible to use BOOTIF=00-12-34-56-78-9a, which this patch
does.
- ksdevice=link
loader: first device with link found is activated
dracut: no way to achive this (activate single unspecified device)?
- ksdevice=ibft
loader: activate devcie configrued in iBFT
dracut: use ip=ibft option
---
dracut/parse-anaconda-net.sh | 24 +++++++++++++++++++-----
1 file changed, 19 insertions(+), 5 deletions(-)
diff --git a/dracut/parse-anaconda-net.sh b/dracut/parse-anaconda-net.sh
index 411b1f5..4b5f9a5 100755
--- a/dracut/parse-anaconda-net.sh
+++ b/dracut/parse-anaconda-net.sh
@@ -5,26 +5,40 @@ net_conf=/etc/cmdline.d/75-anaconda-network-options.conf
check_depr_arg "dns" "nameserver=%s"
+mac_to_bootif() {
+ local bootif=${1}
+ local IFS=':'
+ bootif=$(for i in ${bootif} ; do echo -n $i-; done)
+ bootif=${bootif%-}
+ bootif="01-$bootif"
+ echo $bootif
+}
+
# handle ksdevice (tell us which device to use for ip= stuff later)
export ksdevice=""
ksdev_val=$(getarg ksdevice=)
if [ -n "$ksdev_val" ]; then
case "$ksdev_val" in
link)
- warn "'ksdevice=link' does nothing (it's the default behavior)"
+ warn "'ksdevice=link' is not supported."
;;
ibft)
warn "'ksdevice=ibft' is deprecated. Using 'ip=ibft' instead."
echo "ip=ibft" > $net_conf
- ksdevice="ibft0"
;;
bootif)
warn "'ksdevice=bootif' does nothing (BOOTIF is used by default if present)"
;;
??:??:??:??:??:??)
- warn "'ksdevice=<MAC>' is deprecated. Using 'ifname=ksdev0:<MAC>' instead."
- ksdevice="ksdev0"
- echo "ifname=$ksdevice:$ksdev_val" > $net_conf
+
+ BOOTIF=$(getarg 'BOOTIF=')
+ if [ -n "$BOOTIF" ] ; then
+ warn "'ksdevice=<MAC>' is deprecated. Supplied BOOTIF takes precedence."
+ else
+ bootif=$(mac_to_bootif "$ksdev_val")
+ warn "'ksdevice=<MAC>' is deprecated. Using BOOTIF=$bootif instead."
+ echo "BOOTIF=$bootif" > $net_conf
+ fi
;;
*) ksdevice="$ksdev_val" ;;
esac
--
1.7.11.7
11 years, 2 months