aboutsummaryrefslogtreecommitdiff
path: root/textw
diff options
context:
space:
mode:
authorwiktor w brodlo <wiktor@brodlo.net>2011-06-15 16:59:54 +0000
committerwiktor w brodlo <wiktor@brodlo.net>2011-06-15 16:59:54 +0000
commit2590d96369d0217e31dc2812690dde61dac417b5 (patch)
tree82276f787b08a28548e342c7921486f1acefab9f /textw
parentfirst commit (diff)
downloadanaconda-2590d96369d0217e31dc2812690dde61dac417b5.tar.gz
anaconda-2590d96369d0217e31dc2812690dde61dac417b5.tar.bz2
anaconda-2590d96369d0217e31dc2812690dde61dac417b5.zip
Initial import from Sabayon (ver 0.9.9.56)
Diffstat (limited to 'textw')
-rw-r--r--textw/Makefile.am24
-rw-r--r--textw/complete_text.py65
-rw-r--r--textw/constants_text.py68
-rw-r--r--textw/keyboard_text.py67
-rw-r--r--textw/language_text.py70
-rw-r--r--textw/netconfig_text.py285
-rw-r--r--textw/network_text.py33
-rw-r--r--textw/partition_text.py321
-rw-r--r--textw/progress_text.py142
-rw-r--r--textw/statusline_text.py78
-rw-r--r--textw/task_text.py28
-rw-r--r--textw/timezone_text.py131
-rw-r--r--textw/upgrade_bootloader_text.py183
-rw-r--r--textw/upgrade_text.py258
-rw-r--r--textw/userauth_text.py238
-rw-r--r--textw/welcome_text.py47
-rw-r--r--textw/zipl_text.py102
17 files changed, 2140 insertions, 0 deletions
diff --git a/textw/Makefile.am b/textw/Makefile.am
new file mode 100644
index 0000000..2624967
--- /dev/null
+++ b/textw/Makefile.am
@@ -0,0 +1,24 @@
+# textw/Makefile.am for anaconda
+#
+# Copyright (C) 2009 Red Hat, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as published
+# by the Free Software Foundation; either version 2.1 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+# Author: David Cantrell <dcantrell@redhat.com>
+
+pkgpyexecdir = $(pyexecdir)/py$(PACKAGE_NAME)
+textwdir = $(pkgpyexecdir)/textw
+textw_PYTHON = *.py
+
+MAINTAINERCLEANFILES = Makefile.in
diff --git a/textw/complete_text.py b/textw/complete_text.py
new file mode 100644
index 0000000..c2f3296
--- /dev/null
+++ b/textw/complete_text.py
@@ -0,0 +1,65 @@
+#
+# complete_text.py: text mode congratulations windows
+#
+# Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006 Red Hat, Inc.
+# All rights reserved.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty 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, see <http://www.gnu.org/licenses/>.
+#
+
+from snack import *
+from constants_text import *
+from constants import *
+import gettext
+_ = lambda x: gettext.ldgettext("anaconda", x)
+
+class FinishedWindow:
+
+ def __call__ (self, screen, anaconda):
+ bootstr = ""
+ buttonstr = _("Exit")
+
+ bottomstr = _("<Enter> to exit")
+
+ screen.pushHelpLine (string.center(bottomstr, screen.width))
+
+ import pyanaconda.platform as platform
+ if isinstance(anaconda.platform, platform.S390):
+ txt = _("Congratulations, your %s installation is complete.\n\n") % (productName,)
+
+ if not anaconda.canReIPL:
+ buttonstr = _("Shutdown")
+
+ txt = txt + _("Please shutdown to use the installed system.\n")
+ else:
+ txt = txt + _("Please reboot to use the installed system.\n")
+
+ if not anaconda.reIPLMessage is None:
+ txt = txt + "\n" + anaconda.reIPLMessage + "\n\n"
+
+ txt = txt + _("Note that updates may be available to ensure the proper "
+ "functioning of your system and installation of these "
+ "updates is recommended after the reboot.")
+ else:
+ txt = _("Congratulations, your %s installation is complete.\n\n"
+ "Please reboot to use the installed system. "
+ "Note that updates may be available to ensure the proper "
+ "functioning of your system and installation of these "
+ "updates is recommended after the reboot.") %(productName,)
+
+
+ rc = ButtonChoiceWindow (screen, _("Complete"), txt,
+ [ buttonstr ], help = "finished", width=60)
+
+ return INSTALL_OK
diff --git a/textw/constants_text.py b/textw/constants_text.py
new file mode 100644
index 0000000..1561d5a
--- /dev/null
+++ b/textw/constants_text.py
@@ -0,0 +1,68 @@
+#
+# constants_text.py: text mode constants
+#
+# Copyright (C) 2000, 2001, 2002 Red Hat, Inc. All rights reserved.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty 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, see <http://www.gnu.org/licenses/>.
+#
+
+from constants import *
+import gettext
+_ = lambda x: gettext.ldgettext("anaconda", x)
+
+INSTALL_OK = 0
+INSTALL_BACK = -1
+INSTALL_NOOP = -2
+
+class Translator:
+ """A simple class to facilitate on-the-fly translation for newt buttons"""
+ def __init__(self, button, check):
+ self.button = button
+ self.check = check
+
+ def __getitem__(self, which):
+ if which == 0:
+ return _(self.button)
+ elif which == 1:
+ return self.check
+ raise IndexError
+
+ def __len__(self):
+ return 2
+
+TEXT_OK_STR = N_("OK")
+TEXT_OK_CHECK = "ok"
+TEXT_OK_BUTTON = Translator(TEXT_OK_STR, TEXT_OK_CHECK)
+
+TEXT_CANCEL_STR = N_("Cancel")
+TEXT_CANCEL_CHECK = "cancel"
+TEXT_CANCEL_BUTTON = Translator(TEXT_CANCEL_STR, TEXT_CANCEL_CHECK)
+
+TEXT_BACK_STR = N_("Back")
+TEXT_BACK_CHECK = "back"
+TEXT_BACK_BUTTON = Translator(TEXT_BACK_STR, TEXT_BACK_CHECK)
+
+TEXT_YES_STR = N_("Yes")
+TEXT_YES_CHECK = "yes"
+TEXT_YES_BUTTON = Translator(TEXT_YES_STR, TEXT_YES_CHECK)
+
+TEXT_NO_STR = N_("No")
+TEXT_NO_CHECK = "no"
+TEXT_NO_BUTTON = Translator(TEXT_NO_STR, TEXT_NO_CHECK)
+
+TEXT_EDIT_STR = N_("Edit")
+TEXT_EDIT_CHECK = "edit"
+TEXT_EDIT_BUTTON = Translator(TEXT_EDIT_STR, TEXT_EDIT_CHECK)
+
+TEXT_F12_CHECK = "F12"
diff --git a/textw/keyboard_text.py b/textw/keyboard_text.py
new file mode 100644
index 0000000..aa0201a
--- /dev/null
+++ b/textw/keyboard_text.py
@@ -0,0 +1,67 @@
+#
+# keyboard_text: text mode keyboard setup dialogs
+#
+# Copyright (C) 2001, 2002 Red Hat, Inc. All rights reserved.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty 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, see <http://www.gnu.org/licenses/>.
+#
+
+import isys
+from snack import *
+from constants_text import *
+from flags import flags
+
+from constants import *
+import gettext
+_ = lambda x: gettext.ldgettext("anaconda", x)
+
+import logging
+log = logging.getLogger("anaconda")
+
+class KeyboardWindow:
+ def __call__(self, screen, anaconda):
+ if flags.serial or flags.virtpconsole:
+ return INSTALL_NOOP
+ keyboards = anaconda.keyboard.modelDict.keys()
+ keyboards.sort ()
+
+ if anaconda.keyboard.beenset:
+ default = anaconda.keyboard.get ()
+ else:
+ default = anaconda.instLanguage.getDefaultKeyboard(anaconda.rootPath)
+
+ if default not in keyboards:
+ default = 'us'
+
+ (button, choice) = \
+ ListboxChoiceWindow(screen, _("Keyboard Selection"),
+ _("Which model keyboard is attached to this computer?"), keyboards,
+ buttons = [TEXT_OK_BUTTON, TEXT_BACK_BUTTON], width = 30, scroll = 1, height = 8,
+ default = default, help = "kybd")
+
+ if button == TEXT_BACK_CHECK:
+ return INSTALL_BACK
+
+ anaconda.keyboard.set (keyboards[choice])
+ anaconda.keyboard.beenset = 1
+
+ anaconda.keyboard.activate()
+
+ # FIXME: eventually, kbd.activate will do this
+ try:
+ isys.loadKeymap(keyboards[choice])
+ except SystemError, (errno, msg):
+ log.error("Could not install keymap %s: %s" % (keyboards[choice], msg))
+ return INSTALL_OK
+
diff --git a/textw/language_text.py b/textw/language_text.py
new file mode 100644
index 0000000..14c8503
--- /dev/null
+++ b/textw/language_text.py
@@ -0,0 +1,70 @@
+#
+# language_text.py: text mode language selection dialog
+#
+# Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007 Red Hat, Inc.
+# All rights reserved.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty 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, see <http://www.gnu.org/licenses/>.
+#
+
+from snack import *
+from constants_text import *
+
+from constants import *
+import gettext
+_ = lambda x: gettext.ldgettext("anaconda", x)
+
+import logging
+log = logging.getLogger("anaconda")
+
+class LanguageWindow:
+ def __call__(self, screen, anaconda):
+ languages = anaconda.instLanguage.available ()
+ languages.sort()
+
+ current = anaconda.instLanguage.instLang
+
+ height = min((8, len(languages)))
+ buttons = [TEXT_OK_BUTTON, TEXT_BACK_BUTTON]
+
+ translated = []
+ for lang in languages:
+ translated.append ((_(lang), anaconda.instLanguage.getLangByName(lang)))
+ (button, choice) = \
+ ListboxChoiceWindow(screen, _("Language Selection"),
+ _("What language would you like to use during the "
+ "installation process?"), translated,
+ buttons, width = 30, default = _(current), scroll = 1,
+ height = height, help = "lang")
+
+ if button == TEXT_BACK_CHECK:
+ return INSTALL_BACK
+
+ if anaconda.instLanguage.getFontFile(choice) == "none":
+ ButtonChoiceWindow(screen, "Language Unavailable",
+ "%s display is unavailable in text mode. The "
+ "installation will continue in English." % (choice,),
+ buttons=[TEXT_OK_BUTTON])
+ anaconda.instLanguage.instLang = choice
+ anaconda.instLanguage.systemLang = choice
+ anaconda.timezone.setTimezoneInfo(anaconda.instLanguage.getDefaultTimeZone(anaconda.rootPath))
+ return INSTALL_OK
+
+ anaconda.instLanguage.instLang = choice
+ anaconda.instLanguage.systemLang = choice
+ anaconda.timezone.setTimezoneInfo(anaconda.instLanguage.getDefaultTimeZone(anaconda.rootPath))
+
+ anaconda.intf.drawFrame()
+
+ return INSTALL_OK
diff --git a/textw/netconfig_text.py b/textw/netconfig_text.py
new file mode 100644
index 0000000..4cea192
--- /dev/null
+++ b/textw/netconfig_text.py
@@ -0,0 +1,285 @@
+#
+# netconfig_text.py: Configure a network interface now.
+#
+# Copyright (C) 2008 Red Hat, Inc.
+# All rights reserved.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty 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, see <http://www.gnu.org/licenses/>.
+#
+# Author(s): Chris Lumens <clumens@redhat.com>
+# David Cantrell <dcantrell@redhat.com>
+#
+
+
+import isys
+import network
+from snack import *
+from constants_text import *
+
+import gettext
+_ = lambda x: gettext.ldgettext("anaconda", x)
+
+class NetworkConfiguratorText:
+ def _handleIPError(self, field, errmsg):
+ self.anaconda.intf.messageWindow(_("Error With Data"),
+ _("An error occurred converting the "
+ "value entered for "
+ "\"%(field)s\":\n%(errmsg)s") \
+ % {'field': field, 'errmsg': errmsg})
+
+ def _handleIPMissing(self, field):
+ self.anaconda.intf.messageWindow(_("Error With Data"),
+ _("A value is required for the field %s") % field)
+
+ def _dhcpToggled(self, *args):
+ if self.dhcpCheckbox.selected():
+ self.ipv4Address.setFlags(FLAG_DISABLED, FLAGS_SET)
+ self.ipv4Netmask.setFlags(FLAG_DISABLED, FLAGS_SET)
+ #self.ipv6Address.setFlags(FLAG_DISABLED, FLAGS_SET)
+ #self.ipv6Netmask.setFlags(FLAG_DISABLED, FLAGS_SET)
+ self.gatewayEntry.setFlags(FLAG_DISABLED, FLAGS_SET)
+ self.nameserverEntry.setFlags(FLAG_DISABLED, FLAGS_SET)
+ else:
+ self.ipv4Address.setFlags(FLAG_DISABLED, int(self.ipv4Checkbox.selected()))
+ self.ipv4Netmask.setFlags(FLAG_DISABLED, int(self.ipv4Checkbox.selected()))
+ #self.ipv6Address.setFlags(FLAG_DISABLED, int(self.ipv6Checkbox.selected()))
+ #self.ipv6Netmask.setFlags(FLAG_DISABLED, int(self.ipv6Checkbox.selected()))
+ self.gatewayEntry.setFlags(FLAG_DISABLED, FLAGS_RESET)
+ self.nameserverEntry.setFlags(FLAG_DISABLED, FLAGS_RESET)
+
+ def _ipv4Toggled(self, *args):
+ if self.dhcpCheckbox.selected():
+ return
+
+ flag = FLAGS_RESET
+ if not self.ipv4Checkbox.selected():
+ flag = FLAGS_SET
+
+ self.ipv4Address.setFlags(FLAG_DISABLED, flag)
+ self.ipv4Netmask.setFlags(FLAG_DISABLED, flag)
+
+ #def _ipv6Toggled(self, *args):
+ # if self.dhcpCheckbox.selected():
+ # return
+ #
+ # flag = FLAGS_RESET
+ # if not self.ipv6Checkbox.selected():
+ # flag = FLAGS_SET
+ #
+ # self.ipv6Address.setFlags(FLAG_DISABLED, flag)
+ # self.ipv6Netmask.setFlags(FLAG_DISABLED, flag)
+
+ def __init__(self, screen, anaconda):
+ self.screen = screen
+ self.anaconda = anaconda
+
+ def run(self):
+ grid = GridFormHelp(self.screen, _("Enable network interface"), "netconfig",
+ 1, 9)
+
+ tb = TextboxReflowed(60, _("This requires that you have an active "
+ "network connection during the installation "
+ "process. Please configure a network "
+ "interface."))
+ grid.add(tb, 0, 0, anchorLeft = 1, padding = (0, 0, 0, 1))
+
+ self.interfaceList = CheckboxTree(height=3, scroll=1)
+
+ netdevs = self.anaconda.network.available()
+ devs = netdevs.keys()
+ devs.sort()
+ ksdevice = self.anaconda.network.getKSDevice()
+ if ksdevice:
+ ksdevice = ksdevice.get('DEVICE')
+ selected_interface = None
+
+ for dev in devs:
+ hwaddr = netdevs[dev].get("HWADDR")
+
+ if hwaddr:
+ desc = "%s - %.50s" % (dev, hwaddr)
+ else:
+ desc = dev
+
+ if selected_interface is None:
+ selected_interface = desc
+
+ if ksdevice and ksdevice == dev:
+ selected_interface = desc
+
+ self.interfaceList.append(desc)
+
+ if selected_interface:
+ self.interfaceList.setCurrent(selected_interface)
+ else:
+ self.interfaceList.setCurrent(0)
+
+ grid.add(self.interfaceList, 0, 1, padding = (0, 0, 0, 1))
+
+ self.dhcpCheckbox = Checkbox(_("Use dynamic IP configuration (DHCP)"), 1)
+ grid.add(self.dhcpCheckbox, 0, 2, anchorLeft = 1)
+
+ self.ipv4Checkbox = Checkbox(_("Enable IPv4 support"), 1)
+ grid.add(self.ipv4Checkbox, 0, 3, anchorLeft = 1)
+
+ #self.ipv6Checkbox = Checkbox(_("Enable IPv6 support"), 0)
+ #grid.add(self.ipv6Checkbox, 0, 4, anchorLeft = 1, padding = (0, 0, 0, 1))
+
+ ipv4Grid = Grid(4, 1)
+ ipv4Grid.setField(Label(_("IPv4 Address:")), 0, 0, padding = (0, 0, 1, 0))
+ self.ipv4Address = Entry(20, scroll=1)
+ ipv4Grid.setField(self.ipv4Address, 1, 0)
+ ipv4Grid.setField(Label("/"), 2, 0)
+ self.ipv4Netmask = Entry(20, scroll=0)
+ ipv4Grid.setField(self.ipv4Netmask, 3, 0)
+
+ grid.add(ipv4Grid, 0, 5, anchorLeft = 1)
+
+ #ipv6Grid = Grid(4, 1)
+ #ipv6Grid.setField(Label(_("IPv6 Address:")), 0, 0, padding = (0, 0, 1, 0))
+ #self.ipv6Address = Entry(20, scroll=1)
+ #ipv6Grid.setField(self.ipv6Address, 1, 0)
+ #ipv6Grid.setField(Label("/"), 2, 0)
+ #self.ipv6Netmask = Entry(20, scroll=0)
+ #ipv6Grid.setField(self.ipv6Netmask, 3, 0)
+
+ #grid.add(ipv6Grid, 0, 6, anchorLeft = 1)
+
+ extraGrid = Grid(4, 1)
+ extraGrid.setField(Label(_("Gateway:")), 0, 0, padding = (0, 0, 1, 0))
+ self.gatewayEntry = Entry(20, scroll=1)
+ extraGrid.setField(self.gatewayEntry, 1, 0, padding = (0, 0, 2, 0))
+ extraGrid.setField(Label(_("Nameserver:")), 2, 0, padding = (0, 0, 1, 0))
+ self.nameserverEntry = Entry(20, scroll=1)
+ extraGrid.setField(self.nameserverEntry, 3, 0)
+
+ grid.add(extraGrid, 0, 7, anchorLeft = 1)
+
+ buttons = ButtonBar(self.screen, [TEXT_OK_BUTTON, TEXT_BACK_BUTTON] )
+ grid.add(buttons, 0, 8, anchorLeft = 1, growx = 1)
+
+ self.dhcpCheckbox.setCallback(self._dhcpToggled)
+ self.ipv4Checkbox.setCallback(self._ipv4Toggled)
+ #self.ipv6Checkbox.setCallback(self._ipv6Toggled)
+
+ # Call these functions to set initial UI state.
+ self._ipv4Toggled()
+ #self._ipv6Toggled()
+ self._dhcpToggled()
+
+ netdevs = self.anaconda.network.available()
+
+ while True:
+ result = grid.run()
+ button = buttons.buttonPressed(result)
+
+ if button == TEXT_BACK_CHECK:
+ self.screen.popWindow()
+ return INSTALL_BACK
+
+ selected = map(lambda x: x.split()[0], self.interfaceList.getSelection())
+ if selected is None or selected == []:
+ self.anaconda.intf.messageWindow(_("Missing Device"),
+ _("You must select a network device"))
+ continue
+
+ for name, dev in netdevs.items():
+ if name in selected:
+ dev.set(('ONBOOT', 'yes'))
+ else:
+ dev.set(('ONBOOT', 'no'))
+
+ selected_netdevs = []
+ for devname in selected:
+ if not netdevs.has_key(devname):
+ continue
+
+ netdev = netdevs[devname]
+ selected_netdevs.append(netdev)
+ netdev.set(("ONBOOT", "yes"))
+
+ if self.dhcpCheckbox.selected():
+ netdev.set(("BOOTPROTO", "dhcp"))
+ else:
+ netdev.set(("BOOTPROTO", "static"))
+ ipv4addr = self.ipv4Address.value()
+ ipv4nm = self.ipv4Netmask.value()
+ gateway = self.gatewayEntry.value()
+ ns = self.nameserverEntry.value()
+
+ try:
+ network.sanityCheckIPString(ipv4addr)
+ netdev.set(("IPADDR", ipv4addr))
+ except network.IPMissing, msg:
+ self._handleIPMissing(_("IP Address"))
+ continue
+ except network.IPError, msg:
+ self._handleIPError(_("IP Address"), msg)
+ continue
+
+ if ipv4nm.find('.') == -1:
+ # user provided a CIDR prefix
+ try:
+ if int(ipv4nm) > 32 or int(ipv4nm) < 0:
+ msg = _("IPv4 CIDR prefix must be between 0 and 32.")
+ self._handleIPError(_("IPv4 Network Mask"), msg)
+ continue
+ else:
+ ipv4nm = isys.prefix2netmask(int(ipv4nm))
+ netdev.set(("NETMASK", ipv4nm))
+ except:
+ self._handleIPMissing(_("IPv4 Network Mask"))
+ continue
+ else:
+ # user provided a dotted-quad netmask
+ try:
+ network.sanityCheckIPString(ipv4nm)
+ netdev.set(("NETMASK", ipv4nm))
+ except network.IPMissing, msg:
+ self._handleIPMissing(_("IPv4 Network Mask"))
+ continue
+ except network.IPError, msg:
+ self._handleIPError(_("IPv4 Network Mask "), msg)
+ continue
+
+ try:
+ if gateway:
+ network.sanityCheckIPString(gateway)
+ netdev.set(("GATEWAY", gateway))
+ except network.IPMissing, msg:
+ pass
+ except network.IPError, msg:
+ self._handleIPError(_("Gateway"), msg)
+ continue
+
+ try:
+ if ns:
+ network.sanityCheckIPString(ns)
+ netdev.set(("DNS1", ns))
+ except network.IPMissing, msg:
+ pass
+ except network.IPError, msg:
+ self._handleIPError(_("Nameserver"), msg)
+ continue
+
+ w = self.anaconda.intf.waitWindow(_("Configuring Network Interfaces"), _("Waiting for NetworkManager"))
+ result = self.anaconda.network.bringUp(devices=selected_netdevs)
+ w.pop()
+ if result:
+ break
+ else:
+ self.anaconda.intf.messageWindow(_("Error"), _("Error configuring network device"), _("Error configuring network device %s") % netdev.get('DEVICE'))
+
+ self.screen.popWindow()
+ return INSTALL_OK
diff --git a/textw/network_text.py b/textw/network_text.py
new file mode 100644
index 0000000..26499b8
--- /dev/null
+++ b/textw/network_text.py
@@ -0,0 +1,33 @@
+#
+# network_text.py: text mode network configuration dialogs
+#
+# Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006 Red Hat, Inc.
+# All rights reserved.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty 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, see <http://www.gnu.org/licenses/>.
+#
+# Author(s): Jeremy Katz <katzj@redhat.com>
+# Michael Fulbright <msf@redhat.com>
+# David Cantrell <dcantrell@redhat.com>
+#
+from constants_text import *
+import network
+
+class HostnameWindow:
+ def __call__(self, screen, anaconda):
+ hname = network.getDefaultHostname(anaconda)
+ anaconda.network.hostname = hname
+ return INSTALL_OK
+
+# vim:tw=78:ts=4:et:sw=4
diff --git a/textw/partition_text.py b/textw/partition_text.py
new file mode 100644
index 0000000..f021e4f
--- /dev/null
+++ b/textw/partition_text.py
@@ -0,0 +1,321 @@
+#
+# partition_text.py: allows the user to choose how to partition their disks
+# in text mode
+#
+# Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007 Red Hat, Inc.
+# All rights reserved.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty 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, see <http://www.gnu.org/licenses/>.
+#
+# Author(s): Jeremy Katz <katzj@redhat.com>
+#
+
+import os, sys
+import isys
+import string
+import copy
+import network
+import parted
+from partIntfHelpers import *
+from snack import *
+from constants_text import *
+from constants import *
+
+import gettext
+_ = lambda x: gettext.ldgettext("anaconda", x)
+
+import logging
+log = logging.getLogger("anaconda")
+
+class PartitionTypeWindow:
+ def typeboxChange(self, (typebox, drivelist)):
+ flag = FLAGS_RESET
+ if typebox.current() == CLEARPART_TYPE_NONE:
+ flag = FLAGS_SET
+ # XXX need a way to disable the checkbox tree
+
+ def clearDrivelist(self):
+ # XXX remove parted object refs
+ # need to put in clear() method for checkboxtree in snack
+ self.drivelist.key2item = {}
+ self.drivelist.item2key = {}
+
+ def __call__(self, screen, anaconda):
+ self.anaconda = anaconda
+
+ while 1:
+ g = GridFormHelp(screen, _("Partitioning Type"), "autopart", 1, 6)
+
+ txt = TextboxReflowed(65, _("Installation requires partitioning of your hard drive. The default layout is suitable for most users. Select what space to use and which drives to use as the install target."))
+ g.add(txt, 0, 0, (0, 0, 0, 0))
+
+ opts = ((_("Use entire drive"), CLEARPART_TYPE_ALL),
+ (_("Replace existing Linux system"), CLEARPART_TYPE_LINUX),
+ (_("Use free space"), CLEARPART_TYPE_NONE))
+ typebox = Listbox(height = len(opts), scroll = 0)
+ for (txt, val) in opts:
+ typebox.append(txt, val)
+
+ if anaconda.storage.clearPartType is None:
+ preselection = CLEARPART_TYPE_LINUX
+ else:
+ preselection = anaconda.storage.clearPartType
+ typebox.setCurrent(preselection)
+
+ g.add(typebox, 0, 1, (0, 1, 0, 0))
+
+ # list of drives to select which to clear
+ subgrid = Grid(1, 2)
+ subgrid.setField(TextboxReflowed(55, _("Which drive(s) do you want to "
+ "use for this installation?")),
+ 0, 0)
+ drivelist = CheckboxTree(height=2, scroll=1)
+ subgrid.setField(drivelist, 0, 1)
+ g.add(subgrid, 0, 2, (0, 1, 0, 0))
+
+ bb = ButtonBar(screen, [ TEXT_OK_BUTTON, TEXT_BACK_BUTTON ])
+ g.add(bb, 0, 5, (0,1,0,0))
+
+
+ typebox.setCallback(self.typeboxChange, (typebox, drivelist))
+ self.drivelist = drivelist
+
+ g.addHotKey("F2")
+ screen.pushHelpLine (_("<Space>,<+>,<-> selection | <F2> Add drive | <F12> next screen"))
+
+ # restore the drive list each time
+ disks = anaconda.storage.partitioned
+ cleardrives = anaconda.storage.clearPartDisks
+
+ for disk in disks:
+ model = disk.model
+
+ if not cleardrives or len(cleardrives) < 1:
+ selected = 1
+ else:
+ if disk in cleardrives:
+ selected = 1
+ else:
+ selected = 0
+
+ sizestr = "%8.0f MB" % (disk.size,)
+ diskdesc = "%6s %s (%s)" % (disk.name, sizestr, model[:23],)
+
+ drivelist.append(diskdesc, selected = selected)
+
+ rc = g.run()
+
+ if len(self.drivelist.getSelection()) > 0:
+ sel = map(lambda s: s.split()[0], self.drivelist.getSelection())
+ else:
+ sel = []
+ partmethod_ans = typebox.current()
+ res = bb.buttonPressed(rc)
+
+ self.clearDrivelist()
+ screen.popHelpLine()
+ screen.popWindow()
+
+ if rc == "F2":
+ if self.addDriveDialog(screen) != INSTALL_BACK:
+ anaconda.storage.reset()
+ anaconda.bootloader.updateDriveList()
+ continue
+
+ if res == TEXT_BACK_CHECK:
+ return INSTALL_BACK
+
+ if anaconda.storage.checkNoDisks():
+ continue
+
+ if len(sel) < 1:
+ mustHaveSelectedDrive(anaconda.intf)
+ continue
+
+ anaconda.dispatch.skipStep("autopartitionexecute", skip = 0)
+ anaconda.storage.doAutoPart = True
+ anaconda.storage.clearPartType = partmethod_ans
+ anaconda.storage.clearPartDisks = sel
+ break
+
+ # ask to review autopartition layout - but only if it's not custom partitioning
+ anaconda.dispatch.skipStep("partition", skip = 1)
+ anaconda.dispatch.skipStep("bootloader", skip = 1)
+
+ return INSTALL_OK
+
+ def addDriveDialog(self, screen):
+ newdrv = []
+ from storage import iscsi
+ if iscsi.has_iscsi():
+ newdrv.append("Add iSCSI target")
+ if iutil.isS390():
+ newdrv.append( "Add zFCP LUN" )
+ from storage import fcoe
+ if fcoe.has_fcoe():
+ newdrv.append("Add FCoE SAN")
+
+ if len(newdrv) == 0:
+ return INSTALL_BACK
+
+ (button, choice) = ListboxChoiceWindow(screen,
+ _("Advanced Storage Options"),
+ _("How would you like to modify "
+ "your drive configuration?"),
+ newdrv,
+ [ TEXT_OK_BUTTON, TEXT_BACK_BUTTON],
+ width=55, height=3)
+
+ if button == TEXT_BACK_CHECK:
+ return INSTALL_BACK
+ if newdrv[choice] == "Add zFCP LUN":
+ try:
+ return self.addZFCPDriveDialog(screen)
+ except ValueError, e:
+ ButtonChoiceWindow(screen, _("Error"), str(e))
+ return INSTALL_BACK
+ elif newdrv[choice] == "Add FCoE SAN":
+ try:
+ return self.addFcoeDriveDialog(screen)
+ except ValueError, e:
+ ButtonChoiceWindow(screen, _("Error"), str(e))
+ return INSTALL_BACK
+ else:
+ try:
+ return self.addIscsiDriveDialog(screen)
+ except (ValueError, IOError), e:
+ ButtonChoiceWindow(screen, _("Error"), str(e))
+ return INSTALL_BACK
+
+ def addZFCPDriveDialog(self, screen):
+ (button, entries) = EntryWindow(screen,
+ _("Add FCP Device"),
+ _("zSeries machines can access industry-standard SCSI devices via Fibre Channel (FCP). You need to provide a 16 bit device number, a 64 bit World Wide Port Name (WWPN), and a 64 bit FCP LUN for each device."),
+ prompts = [ "Device number",
+ "WWPN",
+ "FCP LUN" ] )
+ if button == TEXT_CANCEL_CHECK:
+ return INSTALL_BACK
+
+ devnum = entries[0].strip()
+ wwpn = entries[1].strip()
+ fcplun = entries[2].strip()
+ try:
+ self.anaconda.storage.zfcp.addFCP(devnum, wwpn, fcplun)
+ except ValueError, e:
+ log.warn(str(e)) # alternatively popup error dialog instead
+
+ return INSTALL_OK
+
+ def addFcoeDriveDialog(self, screen):
+ netdevs = self.anaconda.network.available()
+ devs = netdevs.keys()
+ devs.sort()
+
+ if not devs:
+ ButtonChoiceWindow(screen, _("Error"),
+ _("No network cards present."))
+ return INSTALL_BACK
+
+ grid = GridFormHelp(screen, _("Add FCoE SAN"), "fcoeconfig",
+ 1, 4)
+
+ tb = TextboxReflowed(60,
+ _("Select which NIC is connected to the FCoE SAN."))
+ grid.add(tb, 0, 0, anchorLeft = 1, padding = (0, 0, 0, 1))
+
+ interfaceList = Listbox(height=len(devs), scroll=1)
+ for dev in devs:
+ hwaddr = netdevs[dev].get("HWADDR")
+ if hwaddr:
+ desc = "%s - %.50s" % (dev, hwaddr)
+ else:
+ desc = dev
+
+ interfaceList.append(desc, dev)
+
+ interfaceList.setCurrent(devs[0])
+ grid.add(interfaceList, 0, 1, padding = (0, 1, 0, 0))
+
+ dcbCheckbox = Checkbox(_("Use DCB"), 1)
+ grid.add(dcbCheckbox, 0, 2, anchorLeft = 1)
+
+ buttons = ButtonBar(screen, [TEXT_OK_BUTTON, TEXT_BACK_BUTTON] )
+ grid.add(buttons, 0, 3, anchorLeft = 1, growx = 1)
+
+ result = grid.run()
+ if buttons.buttonPressed(result) == TEXT_BACK_CHECK:
+ screen.popWindow()
+ return INSTALL_BACK
+
+ nic = interfaceList.current()
+ dcb = dcbCheckbox.selected()
+
+ self.anaconda.storage.fcoe.addSan(nic=nic, dcb=dcb,
+ intf=self.anaconda.intf)
+
+ screen.popWindow()
+ return INSTALL_OK
+
+ def addIscsiDriveDialog(self, screen):
+ if not network.hasActiveNetDev():
+ ButtonChoiceWindow(screen, _("Error"),
+ "Must have a network configuration set up "
+ "for iSCSI config. Please boot with "
+ "'linux asknetwork'")
+ return INSTALL_BACK
+
+ (button, entries) = EntryWindow(screen,
+ _("Configure iSCSI Parameters"),
+ _("To use iSCSI disks, you must provide the address of your iSCSI target and the iSCSI initiator name you've configured for your host."),
+ prompts = [ _("Target IP Address"),
+ _("iSCSI Initiator Name"),
+ _("CHAP username"),
+ _("CHAP password"),
+ _("Reverse CHAP username"),
+ _("Reverse CHAP password") ])
+ if button == TEXT_CANCEL_CHECK:
+ return INSTALL_BACK
+
+ (user, pw, user_in, pw_in) = entries[2:]
+
+ target = entries[0].strip()
+ try:
+ count = len(target.split(":"))
+ idx = target.rfind("]:")
+ # Check for IPV6 [IPV6-ip]:port
+ if idx != -1:
+ ip = target[1:idx]
+ port = target[idx+2:]
+ # Check for IPV4 aaa.bbb.ccc.ddd:port
+ elif count == 2:
+ idx = target.rfind(":")
+ ip = target[:idx]
+ port = target[idx+1:]
+ else:
+ ip = target
+ port = "3260"
+ network.sanityCheckIPString(ip)
+ except network.IPMissing, msg:
+ raise ValueError, msg
+ except network.IPError, msg:
+ raise ValueError, msg
+
+ iname = entries[1].strip()
+ if not self.anaconda.storage.iscsi.initiatorSet:
+ self.anaconda.storage.iscsi.initiator = iname
+ self.anaconda.storage.iscsi.addTarget(ip, port, user, pw,
+ user_in, pw_in)
+
+ return INSTALL_OK
diff --git a/textw/progress_text.py b/textw/progress_text.py
new file mode 100644
index 0000000..71ac9e9
--- /dev/null
+++ b/textw/progress_text.py
@@ -0,0 +1,142 @@
+#
+# progress_text.py: text mode install/upgrade progress dialog
+#
+# Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007 Red Hat, Inc.
+# All rights reserved.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty 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, see <http://www.gnu.org/licenses/>.
+#
+import sys
+
+from constants import *
+from snack import *
+from constants_text import *
+from iutil import strip_markup
+
+import gettext
+_ = lambda x: gettext.ldgettext("anaconda", x)
+
+import logging
+log = logging.getLogger("anaconda")
+
+def deunicode_str(txt):
+ """ messages from Entropy are pushed as unicode, but here
+ we can only accept bytestring """
+ if sys.hexversion < 0x3000000:
+ if isinstance(txt, unicode):
+ return txt.encode('raw_unicode_escape')
+ return txt
+ else:
+ return bytes(str(txt), 'raw_unicode_escape')
+
+class InstallProgressWindow:
+ def __init__(self, screen):
+ self.screen = screen
+ self.drawn = False
+
+ self.pct = 0
+
+ def __del__ (self):
+ if self.drawn:
+ self.screen.popWindow ()
+
+ def _setupScreen(self):
+ screen = self.screen
+
+ self.grid = GridForm(self.screen, _("Package Installation"), 1, 6)
+
+ self.width = 65
+ self.progress = Scale(self.width, 100)
+ self.grid.add (self.progress, 0, 1, (0, 1, 0, 0))
+
+ self.label = Label("")
+ self.grid.add(self.label, 0, 2, (0, 1, 0, 0), anchorLeft = 1)
+
+ self.info = Textbox(self.width, 4, "", wrap = 1)
+ self.grid.add(self.info, 0, 3, (0, 1, 0, 0))
+
+ self.grid.draw()
+ screen.refresh()
+ self.drawn = True
+
+ def processEvents(self):
+ if not self.drawn:
+ return
+ self.grid.draw()
+ self.screen.refresh()
+
+ def setShowPercentage(self, val):
+ pass
+
+ def get_fraction(self):
+ return self.pct
+
+ def set_fraction(self, pct):
+ if not self.drawn:
+ self._setupScreen()
+
+ if pct > 1.0:
+ pct = 1.0
+
+ self.progress.set(int(pct * 100))
+ self.pct = pct
+ self.processEvents()
+
+ def set_label(self, txt):
+ if not self.drawn:
+ self._setupScreen()
+
+ self.info.setText(deunicode_str(strip_markup(txt)))
+ self.processEvents()
+
+ def set_text(self, txt):
+ if not self.drawn:
+ self._setupScreen()
+
+ if len(txt) > self.width:
+ txt = txt[:self.width]
+ else:
+ spaces = (self.width - len(txt)) / 2
+ txt = (" " * spaces) + txt
+
+ self.label.setText(deunicode_str(strip_markup(txt)))
+ self.processEvents()
+
+class setupForInstall:
+
+ def __call__(self, screen, anaconda):
+ if anaconda.dir == DISPATCH_BACK:
+ anaconda.intf.setInstallProgressClass(None)
+ return INSTALL_BACK
+
+ anaconda.intf.setInstallProgressClass(InstallProgressWindow(screen))
+ return INSTALL_OK
+
+if __name__ == "__main__":
+ screen = SnackScreen()
+ ipw = InstallProgressWindow(screen)
+
+ import time
+ ipw._setupScreen()
+ time.sleep(2)
+
+ ipw.set_label("testing blah\n<b>blahblahb</b>lahbl ahalsdfkj")
+ ipw.set_text("blah blah blah")
+ ipw.set_fraction(0.25)
+ time.sleep(2)
+
+ p = ipw.get_fraction()
+
+ screen.finish()
+ print(p)
diff --git a/textw/statusline_text.py b/textw/statusline_text.py
new file mode 100644
index 0000000..4a4a3db
--- /dev/null
+++ b/textw/statusline_text.py
@@ -0,0 +1,78 @@
+#
+# statusline_text.py: text mode status line management functions
+#
+# Copyright (C) 2000, 2001 Red Hat, Inc. All rights reserved.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty 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, see <http://www.gnu.org/licenses/>.
+#
+
+# XXX this file appears to be unused.
+
+import string
+import copy
+
+class CleanStatusLine:
+
+ def centerLabel(self, str, space):
+ return string.center(str, space)
+
+ def formatStatusLine(self, args):
+ if len(args) == 1:
+ return self.centerLabel(args[0], self.width)
+
+ nonspaces = 0
+ for i in args:
+ nonspaces = nonspaces + len(i)
+
+ spaceEach = (self.width-nonspaces)/len(args)
+ outstr = ""
+
+ j = 0
+ for i in args:
+ str = self.centerLabel(i, len(i) + spaceEach)
+ outstr = outstr + str
+ j = j + 1
+ if j != len(args):
+ outstr = outstr + "|"
+
+ return outstr
+
+ def setdefaultStatusLine(self, rargs, largs):
+ self.rargs = rargs
+ self.largs = largs
+
+
+# def defaultStatusLine(self):
+# def __str__(self):
+# args = copy.deepcopy(self.largs)
+# args.extend(self.rargs)
+# return self.formatStatusLine(args)
+
+# def customStatusLine(self, optargs):
+ def __str__(self):
+ args = copy.deepcopy(self.largs)
+ if self.optargs != None:
+ args.extend(self.optargs)
+ args.extend(self.rargs)
+ return self.formatStatusLine(args)
+
+
+ def __init__(self, args, optargs=None):
+# self.largs = ["<Tab>/<Alt-Tab> between elements"]
+# self.rargs = ["<F12> next screen"]
+ (self.largs, self.rargs) = args
+ self.optargs = optargs
+
+ self.width = 80
+
diff --git a/textw/task_text.py b/textw/task_text.py
new file mode 100644
index 0000000..17d312b
--- /dev/null
+++ b/textw/task_text.py
@@ -0,0 +1,28 @@
+#
+# task_gui.py: Choose tasks for installation
+#
+# Copyright (C) 2006 Red Hat, Inc. All rights reserved.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty 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, see <http://www.gnu.org/licenses/>.
+#
+
+from constants_text import *
+from constants import *
+
+class TaskWindow:
+ def __call__(self, screen, anaconda):
+ anaconda.backend.resetPackageSelections()
+ anaconda.backend.selectGroup("Core")
+
+ return INSTALL_OK
diff --git a/textw/timezone_text.py b/textw/timezone_text.py
new file mode 100644
index 0000000..c78442a
--- /dev/null
+++ b/textw/timezone_text.py
@@ -0,0 +1,131 @@
+#
+# timezone_text.py: text mode timezone selection dialog
+#
+# Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006 Red Hat, Inc.
+# All rights reserved.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty 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, see <http://www.gnu.org/licenses/>.
+#
+
+import sys
+import string
+import iutil
+from time import *
+from snack import *
+from constants_text import *
+from bootloader import hasWindows
+from scdate.core import zonetab
+
+from constants import *
+import gettext
+_ = lambda x: gettext.ldgettext("anaconda", x)
+
+sys.path.append("/usr/share/system-config-date")
+
+class TimezoneWindow:
+
+ def getTimezoneList(self):
+ zt = zonetab.ZoneTab()
+ zoneList = [ x.tz for x in zt.getEntries() ]
+ zoneList.sort()
+ return zoneList
+
+ def updateSysClock(self):
+ args = ["--hctosys"]
+ if self.c.selected():
+ args.append("--utc")
+
+ iutil.execWithRedirect("hwclock", args)
+ self.g.setTimer(500)
+ self.updateClock()
+
+ def updateClock(self):
+ # disable for now
+ return
+
+# if os.access("/usr/share/zoneinfo/" + self.l.current(), os.R_OK):
+# os.environ['TZ'] = self.l.current()
+# self.label.setText(self.currentTime())
+# else:
+# self.label.setText("")
+
+ def currentTime(self):
+ return "Current time: " + strftime("%X %Z", localtime(time()))
+
+ def __call__(self, screen, anaconda):
+ timezones = self.getTimezoneList()
+ (default, asUtc) = anaconda.timezone.getTimezoneInfo()
+ if not default:
+ default = anaconda.instLanguage.getDefaultTimeZone(anaconda.rootPath)
+
+ bb = ButtonBar(screen, [TEXT_OK_BUTTON, TEXT_BACK_BUTTON])
+ t = TextboxReflowed(30,
+ _("In which time zone are you located?"))
+
+ if not anaconda.ksdata and not hasWindows(anaconda.bootloader):
+ asUtc = True
+
+#
+# disabling this for now
+#
+# self.label = Label(self.currentTime())
+
+ self.l = Listbox(5, scroll = 1, returnExit = 0)
+
+ for tz in timezones:
+ self.l.append(gettext.ldgettext("system-config-date", tz), tz)
+
+ self.l.setCurrent(default.replace("_", " "))
+# self.l.setCallback(self.updateClock)
+
+ self.c = Checkbox(_("System clock uses UTC"), isOn = asUtc)
+# self.c.setCallback(self.updateSysClock)
+
+ self.g = GridFormHelp(screen, _("Time Zone Selection"), "timezone",
+ 1, 5)
+ self.g.add(t, 0, 0)
+# self.g.add(self.label, 0, 1, padding = (0, 1, 0, 0), anchorLeft = 1)
+ self.g.add(self.c, 0, 2, padding = (0, 1, 0, 1), anchorLeft = 1)
+ self.g.add(self.l, 0, 3, padding = (0, 0, 0, 1))
+ self.g.add(bb, 0, 4, growx = 1)
+
+# disabling for now
+# self.updateClock()
+# self.updateSysClock()
+#
+# self.g.setTimer(500)
+#
+# result = "TIMER"
+# while result == "TIMER":
+# result = self.g.run()
+# if result == "TIMER":
+# self.updateClock()
+
+ result = ""
+ while 1:
+ result = self.g.run()
+ rc = bb.buttonPressed (result)
+
+ if rc == TEXT_BACK_CHECK:
+ screen.popWindow()
+ return INSTALL_BACK
+ else:
+ break
+
+ screen.popWindow()
+ anaconda.timezone.setTimezoneInfo(self.l.current().replace(" ", "_"), asUtc = self.c.selected())
+
+ return INSTALL_OK
+
+
diff --git a/textw/upgrade_bootloader_text.py b/textw/upgrade_bootloader_text.py
new file mode 100644
index 0000000..db736f3
--- /dev/null
+++ b/textw/upgrade_bootloader_text.py
@@ -0,0 +1,183 @@
+#
+# upgrade_bootloader_text.py: text bootloader dialog for upgrades
+#
+# Copyright (C) 2002 Red Hat, Inc. All rights reserved.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty 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, see <http://www.gnu.org/licenses/>.
+#
+# Author(s): Jeremy Katz <katzj@redhat.com>
+#
+
+from snack import *
+from constants_text import *
+from flags import flags
+import string
+from booty import checkbootloader
+from storage.devices import devicePathToName
+
+from constants import *
+import gettext
+_ = lambda x: gettext.ldgettext("anaconda", x)
+
+import logging
+log = logging.getLogger("anaconda")
+
+class UpgradeBootloaderWindow:
+ def _ideToLibata(self, rootPath):
+ try:
+ f = open("/proc/modules", "r")
+ buf = f.read()
+ if buf.find("libata") == -1:
+ return False
+ except:
+ log.debug("error reading /proc/modules")
+ pass
+
+ try:
+ f = open(rootPath + "/etc/modprobe.conf")
+ except:
+ log.debug("error reading /etc/modprobe.conf")
+ return False
+
+ modlines = f.readlines()
+ f.close()
+
+ try:
+ f = open("/tmp/scsidisks")
+ except:
+ log.debug("error reading /tmp/scsidisks")
+ return False
+ mods = []
+ for l in f.readlines():
+ (disk, mod) = l.split()
+ if mod.strip() not in mods:
+ mods.append(mod.strip())
+ f.close()
+
+ for l in modlines:
+ stripped = l.strip()
+
+ if stripped == "" or stripped[0] == "#":
+ continue
+
+ if stripped.find("scsi_hostadapter") != -1:
+ mod = stripped.split()[-1]
+ if mod in mods:
+ mods.remove(mod)
+
+ if len(mods) > 0:
+ return True
+ return False
+
+ def __call__(self, screen, anaconda):
+ self.screen = screen
+ self.dispatch = anaconda.dispatch
+ self.bl = anaconda.bootloader
+
+ newToLibata = self._ideToLibata(anaconda.rootPath)
+ (self.type, self.bootDev) = \
+ checkbootloader.getBootloaderTypeAndBoot(anaconda.rootPath, storage=anaconda.storage)
+
+ blradio = RadioGroup()
+
+ (update, newbl, nobl) = (0, 0, 0)
+ if not self.dispatch.stepInSkipList("bootloader"):
+ newbl = 1
+ elif self.dispatch.stepInSkipList("instbootloader"):
+ nobl = 1
+ else:
+ if newToLibata or self.type is None or self.bootDev is None:
+ newbl = 1
+ else:
+ update = 1
+
+ if newToLibata or self.type is None or self.bootDev is None:
+ if newToLibata:
+ t = TextboxReflowed(53,
+ _("Due to system changes, your boot loader "
+ "configuration can not be automatically updated."))
+ else:
+ t = TextboxReflowed(53,
+ _("The installer is unable to detect the boot loader "
+ "currently in use on your system."))
+
+
+ self.update_radio = blradio.add(_("Update boot loader configuration"),
+ "update", update)
+ self.update_radio.w.checkboxSetFlags(FLAG_DISABLED, FLAGS_SET)
+ else:
+ t = TextboxReflowed(53,
+ _("The installer has detected the %(type)s "
+ "boot loader currently installed on "
+ "%(bootDev)s.")
+ % {'type': self.type, 'bootDev': self.bootDev})
+
+ self.update_radio = blradio.add(_("Update boot loader configuration"),
+ "update", update)
+
+ self.nobl_radio = blradio.add(_("Skip boot loader updating"),
+ "nobl", nobl)
+ self.newbl_radio = blradio.add(_("Create new boot loader "
+ "configuration"),
+ "newbl", newbl)
+
+ buttons = ButtonBar(screen, [TEXT_OK_BUTTON, TEXT_BACK_BUTTON])
+
+ grid = GridFormHelp(screen, _("Upgrade Boot Loader Configuration"),
+ "bl-upgrade", 1, 5)
+
+ grid.add(t, 0, 0, (0,0,0,1))
+ grid.add(self.update_radio, 0, 1, (0,0,0,0))
+ grid.add(self.nobl_radio, 0, 2, (0,0,0,0))
+ grid.add(self.newbl_radio, 0, 3, (0,0,0,1))
+ grid.add(buttons, 0, 4, growx = 1)
+
+
+ while 1:
+ result = grid.run()
+
+ button = buttons.buttonPressed(result)
+
+ if button == TEXT_BACK_CHECK:
+ screen.popWindow()
+ return INSTALL_BACK
+
+ if blradio.getSelection() == "nobl":
+ self.dispatch.skipStep("bootloadersetup", skip = 1)
+ self.dispatch.skipStep("bootloader", skip = 1)
+ self.dispatch.skipStep("bootloaderadvanced", skip = 1)
+ self.dispatch.skipStep("instbootloader", skip = 1)
+ elif blradio.getSelection() == "newbl":
+ self.dispatch.skipStep("bootloadersetup", skip = 0)
+ self.dispatch.skipStep("bootloader", skip = 0)
+ self.dispatch.skipStep("bootloaderadvanced", skip = 0)
+ self.dispatch.skipStep("instbootloader", skip = 0)
+ self.bl.doUpgradeOnly = 0
+ else:
+ self.dispatch.skipStep("bootloadersetup", skip = 0)
+ self.dispatch.skipStep("bootloader", skip = 1)
+ self.dispatch.skipStep("bootloaderadvanced", skip = 1)
+ self.dispatch.skipStep("instbootloader", skip = 0)
+ self.bl.doUpgradeOnly = 1
+
+ if self.type == "GRUB":
+ self.bl.useGrubVal = 1
+ else:
+ self.bl.useGrubVal = 0
+ self.bl.setDevice(devicePathToName(self.bootDev))
+
+
+
+ screen.popWindow()
+ return INSTALL_OK
diff --git a/textw/upgrade_text.py b/textw/upgrade_text.py
new file mode 100644
index 0000000..f7c8a84
--- /dev/null
+++ b/textw/upgrade_text.py
@@ -0,0 +1,258 @@
+#
+# upgrade_text.py: text mode upgrade dialogs
+#
+# Copyright (C) 2001 Red Hat, Inc. All rights reserved.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty 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, see <http://www.gnu.org/licenses/>.
+#
+
+import isys
+import iutil
+import upgrade
+from constants_text import *
+from snack import *
+from flags import flags
+from constants import *
+from storage.formats import getFormat
+
+import gettext
+_ = lambda x: gettext.ldgettext("anaconda", x)
+
+import logging
+log = logging.getLogger("anaconda")
+
+seenExamineScreen = False
+
+class UpgradeMigrateFSWindow:
+ def __call__ (self, screen, anaconda):
+
+ migent = anaconda.storage.migratableDevices
+
+ g = GridFormHelp(screen, _("Migrate File Systems"), "upmigfs", 1, 4)
+
+ text = (_("This release of %(productName)s supports "
+ "an updated file system, which has several "
+ "benefits over the file system traditionally shipped "
+ "in %(productName)s. This installation program can migrate "
+ "formatted partitions without data loss.\n\n"
+ "Which of these partitions would you like to migrate?") %
+ {'productName': productName})
+
+ tb = TextboxReflowed(60, text)
+ g.add(tb, 0, 0, anchorLeft = 1, padding = (0, 0, 0, 1))
+
+ partlist = CheckboxTree(height=4, scroll=1)
+ for device in migent:
+ if not device.format.exists:
+ migrating = True
+ else:
+ migrating = False
+
+ # FIXME: the fstype at least will be wrong here
+ partlist.append("%s - %s - %s" % (device.path,
+ device.format.type,
+ device.format.mountpoint),
+ device, migrating)
+
+ g.add(partlist, 0, 1, padding = (0, 0, 0, 1))
+
+ buttons = ButtonBar(screen, [TEXT_OK_BUTTON, TEXT_BACK_BUTTON] )
+ g.add(buttons, 0, 3, anchorLeft = 1, growx = 1)
+
+ while 1:
+ result = g.run()
+
+ if (buttons.buttonPressed(result)):
+ result = buttons.buttonPressed(result)
+
+ if result == TEXT_BACK_CHECK:
+ screen.popWindow()
+ return INSTALL_BACK
+
+ # reset
+ # XXX the way to do this is by scheduling and cancelling actions
+ #for entry in migent:
+ # entry.setFormat(0)
+ # entry.setMigrate(0)
+ # entry.fsystem = entry.origfsystem
+
+ for entry in partlist.getSelection():
+ try:
+ newfs = getFormat(entry.format.migratetofs[0])
+ except Exception, e:
+ log.info("failed to get new filesystem type, defaulting to ext3: %s" %(e,))
+ newfs = getFormat("ext3")
+ anaconda.storage.migrateFormat(entry, newfs)
+
+ screen.popWindow()
+ return INSTALL_OK
+
+class UpgradeSwapWindow:
+ def __call__ (self, screen, anaconda):
+ (fsList, suggSize, suggDev) = anaconda.upgradeSwapInfo
+
+ ramDetected = iutil.memInstalled()/1024
+
+ text = _("Recent kernels (2.4 or newer) need significantly more swap than older "
+ "kernels, up to twice the amount of RAM on the "
+ "system. You currently have %dMB of swap configured, but "
+ "you may create additional swap space on one of your "
+ "file systems now.") % (iutil.swapAmount() / 1024)
+
+ tb = TextboxReflowed(60, text)
+ amount = Entry(10, scroll = 0)
+ amount.set(str(suggSize))
+
+ l = len(fsList)
+ scroll = 0
+ if l > 4:
+ l = 4
+ scroll = 1
+ listbox = Listbox(l, scroll = scroll)
+
+ liLabel = Label("%-25s %-15s %8s" % (_("Mount Point"),
+ _("Partition"), _("Free Space")))
+
+ count = 0
+ for (device, size) in fsList:
+ listbox.append("%-25s %-15s %6dMB" % (device.format.mountpoint,
+ device.path,
+ size),
+ count)
+
+ if (device == suggDev):
+ listbox.setCurrent(count)
+
+ count = count + 1
+
+ buttons = ButtonBar(screen, [TEXT_OK_BUTTON, (_("Skip"), "skip"),
+ TEXT_BACK_BUTTON] )
+
+ amGrid = Grid(2, 3)
+ amGrid.setField(Label(_("RAM detected (MB):")), 0, 0, anchorLeft = 1,
+ padding = (0, 0, 1, 0))
+ amGrid.setField(Label(str(ramDetected)), 1, 0, anchorLeft = 1)
+ amGrid.setField(Label(_("Suggested size (MB):")), 0, 1, anchorLeft = 1,
+ padding = (0, 0, 1, 0))
+ amGrid.setField(Label(str(suggSize)), 1, 1, anchorLeft = 1)
+ amGrid.setField(Label(_("Swap file size (MB):")), 0, 2, anchorLeft = 1,
+ padding = (0, 0, 1, 0))
+ amGrid.setField(amount, 1, 2)
+
+ liGrid = Grid(1, 2)
+ liGrid.setField(liLabel, 0, 0)
+ liGrid.setField(listbox, 0, 1)
+
+ g = GridFormHelp(screen, _("Add Swap"), "upgradeswap", 1, 4)
+ g.add(tb, 0, 0, anchorLeft = 1, padding = (0, 0, 0, 1))
+ g.add(amGrid, 0, 1, padding = (0, 0, 0, 1))
+ g.add(liGrid, 0, 2, padding = (0, 0, 0, 1))
+ g.add(buttons, 0, 3, anchorLeft = 1, growx = 1)
+
+ while 1:
+ result = g.run()
+
+ if (buttons.buttonPressed(result)):
+ result = buttons.buttonPressed(result)
+
+ if result == TEXT_BACK_CHECK:
+ screen.popWindow()
+ return INSTALL_BACK
+ elif result == "skip":
+ screen.popWindow()
+ return INSTALL_OK
+
+ val = amount.value()
+
+ try:
+ val = int(val)
+ except ValueError:
+ anaconda.intf.messageWindow(_("Error"),
+ _("The value you entered is not a "
+ "valid number."))
+
+ if type(val) == type(1):
+ (dev, size) = fsList[listbox.current()]
+ if size < (val + 16):
+ anaconda.intf.messageWindow(_("Error"),
+ _("There is not enough space on the "
+ "device you selected for the swap "
+ "partition."))
+ elif val > 2000 or val < 1:
+ anaconda.intf.messageWindow(_("Warning"),
+ _("The swap file must be between 1 "
+ "and 2000 MB in size."))
+ else:
+ screen.popWindow()
+ anaconda.storage.createSwapFile(dev, val)
+ anaconda.dispatch.skipStep("addswap", 1)
+ return INSTALL_OK
+
+ raise ValueError
+
+class UpgradeExamineWindow:
+ def __call__ (self, screen, anaconda):
+ parts = anaconda.rootParts
+
+ height = min(len(parts), 11) + 1
+ if height == 12:
+ scroll = 1
+ else:
+ scroll = 0
+ partList = []
+ partList.append(_("Reinstall System"))
+
+ global seenExamineScreen
+
+ if (not seenExamineScreen and anaconda.dispatch.stepInSkipList("installtype")) or anaconda.upgrade:
+ default = 1
+ else:
+ default = 0
+
+ for (device, desc) in parts:
+ partList.append("%s (%s)" %(desc, device.path))
+
+ (button, choice) = ListboxChoiceWindow(screen, _("System to Upgrade"),
+ _("There seem to be one or more existing Linux installations "
+ "on your system.\n\nPlease choose one to rescue, "
+ "or select 'Reinstall System' to freshly install "
+ "your system."), partList,
+ [ TEXT_OK_BUTTON,
+ TEXT_BACK_BUTTON ],
+ width = 55, scroll = scroll,
+ height = height,
+ default = default,
+ help = "upgraderoot")
+
+ if button == TEXT_BACK_CHECK:
+ return INSTALL_BACK
+ else:
+ if choice == 0:
+ root = None
+ else:
+ root = parts[choice - 1]
+
+ if root is not None:
+ upgrade.setSteps(anaconda)
+ anaconda.upgrade = True
+
+ anaconda.upgradeRoot = [(root[0], root[1])]
+ anaconda.rootParts = parts
+ anaconda.dispatch.skipStep("installtype", skip = 1)
+ else:
+ anaconda.dispatch.skipStep("installtype", skip = 0)
+ anaconda.upgradeRoot = None
+
+ seenExamineScreen = True
+ return INSTALL_OK
diff --git a/textw/userauth_text.py b/textw/userauth_text.py
new file mode 100644
index 0000000..2a41a08
--- /dev/null
+++ b/textw/userauth_text.py
@@ -0,0 +1,238 @@
+#
+# userauth_text.py: text mode authentication setup dialogs
+#
+# Copyright (C) 2000, 2001, 2002, 2008 Red Hat, Inc. All rights reserved.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty 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, see <http://www.gnu.org/licenses/>.
+#
+
+from snack import *
+from constants_text import *
+import cracklib
+
+from constants import *
+import gettext
+_ = lambda x: gettext.ldgettext("anaconda", x)
+
+class RootPasswordWindow:
+ def __call__ (self, screen, anaconda):
+ toplevel = GridFormHelp(screen, _("Root Password"), "rootpw", 1, 3)
+
+ toplevel.add(TextboxReflowed(37,
+ _("Pick a root password. You must "
+ "type it twice to ensure you know "
+ "it and do not make a typing "
+ "mistake. ")),
+ 0, 0, (0, 0, 0, 1))
+
+ if anaconda.users.rootPassword["isCrypted"]:
+ anaconda.users.rootPassword["password"] = ""
+
+ entry1 = Entry(24, password=1,
+ text=anaconda.users.rootPassword["password"])
+ entry2 = Entry(24, password=1,
+ text=anaconda.users.rootPassword["password"])
+ passgrid = Grid(2, 2)
+ passgrid.setField(Label(_("Password:")), 0, 0, (0, 0, 1, 0),
+ anchorLeft=1)
+ passgrid.setField(Label(_("Password (confirm):")), 0, 1, (0, 0, 1, 0),
+ anchorLeft=1)
+ passgrid.setField(entry1, 1, 0)
+ passgrid.setField(entry2, 1, 1)
+ toplevel.add(passgrid, 0, 1, (0, 0, 0, 1))
+
+ bb = ButtonBar(screen, (TEXT_OK_BUTTON, TEXT_BACK_BUTTON))
+ toplevel.add(bb, 0, 2, growx = 1)
+
+ while 1:
+ toplevel.setCurrent(entry1)
+ result = toplevel.run()
+ rc = bb.buttonPressed(result)
+ if rc == TEXT_BACK_CHECK:
+ screen.popWindow()
+ return INSTALL_BACK
+ if len(entry1.value()) < 6:
+ ButtonChoiceWindow(screen, _("Password Length"),
+ _("The root password must be at least 6 characters long."),
+ buttons = [ TEXT_OK_BUTTON ], width = 50)
+ elif entry1.value() != entry2.value():
+ ButtonChoiceWindow(screen, _("Password Mismatch"),
+ _("The passwords you entered were different. Please "
+ "try again."), buttons = [ TEXT_OK_BUTTON ], width = 50)
+ elif self.hasBadChars(entry1.value()):
+ ButtonChoiceWindow(screen, _("Error with Password"),
+ _("Requested password contains non-ASCII characters, "
+ "which are not allowed."),
+ buttons = [ TEXT_OK_BUTTON ], width = 50)
+ else:
+ try:
+ cracklib.FascistCheck(entry1.value())
+ except ValueError, e:
+ msg = gettext.ldgettext("cracklib", e)
+ ret = anaconda.intf.messageWindow(_("Weak Password"),
+ _("You have provided a weak password: %s\n\n"
+ "Would you like to continue with this password?"
+ % (msg, )),
+ type = "yesno", default="no")
+ if ret == 1:
+ break
+ else:
+ break
+
+ entry1.set("")
+ entry2.set("")
+
+ screen.popWindow()
+ anaconda.users.rootPassword["password"] = entry1.value()
+ anaconda.users.rootPassword["isCrypted"] = False
+ return INSTALL_OK
+
+ def hasBadChars(self, pw):
+ allowed = string.digits + string.ascii_letters + \
+ string.punctuation + " "
+ for letter in pw:
+ if letter not in allowed:
+ return True
+ return False
+
+class UserPasswordWindow:
+ def __call__ (self, screen, anaconda):
+ toplevel = GridFormHelp(screen, _("User configuration"), "rootpw", 1, 3)
+
+ toplevel.add(TextboxReflowed(37,
+ _("Setup a username for regular "
+ "(non-administrative) use.")),
+ 0, 0, (0, 0, 0, 1))
+
+ from sabayon.const import LIVE_USER
+ live_user_data = anaconda.users.otherUsers.get(LIVE_USER, {})
+
+ entry_username = Entry(24, text=live_user_data.get("username", ''))
+ entry_fullname = Entry(24, text=live_user_data.get("fullname", ''))
+
+ entry1 = Entry(24, password=1,
+ text=live_user_data.get("password", ''))
+ entry2 = Entry(24, password=1,
+ text=live_user_data.get("password", ''))
+ passgrid = Grid(2, 4)
+
+ passgrid.setField(Label(_("Username:")), 0, 0, (0, 0, 1, 0),
+ anchorLeft=1)
+ passgrid.setField(Label(_("Full name:")), 0, 1, (0, 0, 1, 0),
+ anchorLeft=1)
+ passgrid.setField(Label(_("Password:")), 0, 2, (0, 0, 1, 0),
+ anchorLeft=1)
+ passgrid.setField(Label(_("Password (confirm):")), 0, 3, (0, 0, 1, 0),
+ anchorLeft=1)
+
+ passgrid.setField(entry_username, 1, 0)
+ passgrid.setField(entry_fullname, 1, 1)
+ passgrid.setField(entry1, 1, 2)
+ passgrid.setField(entry2, 1, 3)
+
+ toplevel.add(passgrid, 0, 1, (0, 0, 0, 1))
+
+ bb = ButtonBar(screen, (TEXT_OK_BUTTON, TEXT_BACK_BUTTON))
+ toplevel.add(bb, 0, 2, growx = 1)
+
+ while 1:
+ clean_pass = True
+ toplevel.setCurrent(entry1)
+ result = toplevel.run()
+ rc = bb.buttonPressed(result)
+ if rc == TEXT_BACK_CHECK:
+ screen.popWindow()
+ return INSTALL_BACK
+ if len(entry1.value()) < 6:
+ ButtonChoiceWindow(screen, _("Password Length"),
+ _("User password must be at least 6 characters long."),
+ buttons = [ TEXT_OK_BUTTON ], width = 50)
+ elif entry1.value() != entry2.value():
+ ButtonChoiceWindow(screen, _("Password Mismatch"),
+ _("The passwords you entered were different. Please "
+ "try again."), buttons = [ TEXT_OK_BUTTON ], width = 50)
+ elif self.hasBadChars(entry1.value()):
+ ButtonChoiceWindow(screen, _("Error with Password"),
+ _("Requested password contains non-ASCII characters, "
+ "which are not allowed."),
+ buttons = [ TEXT_OK_BUTTON ], width = 50)
+
+ elif len(entry_username.value()) < 2:
+ anaconda.intf.messageWindow(_("Error with username"),
+ _("Username too short"),
+ custom_icon="error")
+ clean_pass = False
+ elif self.isUsernameAlreadyAvailable(entry_username.value()):
+ self.intf.messageWindow(_("Error with username"),
+ _("Requested username is already taken."),
+ custom_icon="error")
+ self.usernameError()
+
+ if self.hasBadChars(entry_username.value(), spaces = False):
+ anaconda.intf.messageWindow(_("Error with username"),
+ _("Requested username contains "
+ "non-ASCII characters or spaces, which are "
+ "not allowed."),
+ custom_icon="error")
+ clean_pass = False
+ else:
+ try:
+ cracklib.FascistCheck(entry1.value())
+ except ValueError, e:
+ msg = gettext.ldgettext("cracklib", e)
+ ret = anaconda.intf.messageWindow(_("Weak Password"),
+ _("You have provided a weak password: %s\n\n"
+ "Would you like to continue with this password?"
+ % (msg, )),
+ type = "yesno", default="no")
+ if ret == 1:
+ break
+ else:
+ break
+
+ if clean_pass:
+ entry1.set("")
+ entry2.set("")
+
+ screen.popWindow()
+
+ import grp
+ def get_all_groups(user):
+ for group in grp.getgrall():
+ if user in group.gr_mem:
+ yield group.gr_name
+
+ user_data = {
+ 'fullname': entry_fullname.value(),
+ 'password': entry1.value(),
+ 'username': entry_username.value(),
+ 'groups': list(get_all_groups(LIVE_USER)),
+ }
+ anaconda.users.otherUsers[LIVE_USER] = user_data
+
+ return INSTALL_OK
+
+ def hasBadChars(self, pw, spaces = True):
+ allowed = string.digits + string.ascii_letters + \
+ string.punctuation
+ if spaces:
+ allowed += " "
+ for letter in pw:
+ if letter not in allowed:
+ return True
+ return False
+
+ def isUsernameAlreadyAvailable(self, username):
+ import pwd
+ return username in [x.pw_name for x in pwd.getpwall()]
diff --git a/textw/welcome_text.py b/textw/welcome_text.py
new file mode 100644
index 0000000..bf58b58
--- /dev/null
+++ b/textw/welcome_text.py
@@ -0,0 +1,47 @@
+#
+# welcome_text.py: text mode welcome window
+#
+# Copyright (C) 2001, 2002 Red Hat, Inc. All rights reserved.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty 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, see <http://www.gnu.org/licenses/>.
+#
+
+from snack import *
+from constants_text import *
+from constants import *
+import sys
+import gettext
+_ = lambda x: gettext.ldgettext("anaconda", x)
+
+class WelcomeWindow:
+ def __call__(self, screen, anaconda):
+ rc = ButtonChoiceWindow(screen, _("%s") % (productName,),
+ _("Welcome to %s!\n\n")
+ % (productName, ),
+ buttons = [TEXT_OK_BUTTON], width = 50,
+ help = "welcome")
+
+ if anaconda.requiresNetworkInstall():
+ anaconda.intf.messageWindow(_("Network Install Required"),
+ _("Your installation source is set to "
+ "a network location, but no netork "
+ "devices were found on your "
+ "system. To avoid a network "
+ "installation, boot with the full "
+ "DVD, full CD set, or do not pass "
+ "a repo= parameter that specifies "
+ "a network source."))
+ sys.exit(0)
+
+ return INSTALL_OK
diff --git a/textw/zipl_text.py b/textw/zipl_text.py
new file mode 100644
index 0000000..9a1b202
--- /dev/null
+++ b/textw/zipl_text.py
@@ -0,0 +1,102 @@
+#
+# zipl_text.py: text mode z/IPL setup dialog
+#
+# Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006 Red Hat, Inc.
+# All rights reserved.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty 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, see <http://www.gnu.org/licenses/>.
+#
+
+import string
+from snack import *
+from constants_text import *
+
+from constants import *
+from storage.dasd import getDasdPorts
+
+import gettext
+_ = lambda x: gettext.ldgettext("anaconda", x)
+
+class ZiplWindow:
+ def __call__(self, screen, anaconda):
+ self.bl = anaconda.bootloader
+
+ t = TextboxReflowed(53,
+ _("The z/IPL Boot Loader will be installed "
+ "on your system after installation is complete. "
+ "You can now enter any additional kernel and "
+ "chandev parameters which your machine or your "
+ "setup require."))
+
+ kernelparms = ""
+ kernelentry = Entry(48, scroll = 1, returnExit = 1)
+ chandeventry1 = Entry(48, scroll = 1, returnExit = 1)
+ chandeventry2 = Entry(48, scroll = 1, returnExit = 1)
+
+ if self.bl.args and self.bl.args.get():
+ kernelparms = self.bl.args.get()
+ if getDasdPorts() and (kernelparms.find("dasd=") == -1):
+ if len(kernelparms) > 0:
+ kernelparms = "%s dasd=%s" %(kernelparms, getDasdPorts())
+ else:
+ kernelparms = "dasd=%s" %(getDasdPorts(),)
+ kernelentry.set(kernelparms)
+
+ if self.bl.args and self.bl.args.chandevget():
+ cdevs = self.bl.args.chandevget()
+ chandeventry1.set('')
+ chandeventry2.set('')
+ if len(cdevs) > 0:
+ chandeventry1.set(cdevs[0])
+ if len(cdevs) > 1:
+ chandeventry2.set(string.join(cdevs[1:],';'))
+
+ buttons = ButtonBar(screen, [TEXT_OK_BUTTON,
+ TEXT_BACK_BUTTON ] )
+
+ grid = GridFormHelp(screen, _("z/IPL Configuration"),
+ "zipl-s390", 1, 5)
+ grid.add(t, 0, 0)
+ sg = Grid(2, 1)
+ sg.setField(Label(_("Kernel Parameters") + ": "), 0, 0, anchorLeft=1)
+ sg.setField(kernelentry, 1, 0, anchorLeft=1)
+ grid.add(sg, 0, 1, padding = (0, 1, 0, 1))
+ sg = Grid(2, 1)
+ sg.setField(Label(_("Chandev line ") + "1: "), 0, 0, anchorLeft=1)
+ sg.setField(chandeventry1, 1, 0, anchorLeft=1)
+ grid.add(sg, 0, 2, padding = (0, 1, 0, 1))
+ sg = Grid(2, 1)
+ sg.setField(Label(_("Chandev line ") + "2: "), 0, 0, anchorLeft=1)
+ sg.setField(chandeventry2, 1, 0, anchorLeft=1)
+ grid.add(sg, 0, 3, padding = (0, 1, 0, 1))
+ grid.add(buttons, 0, 4, growx = 1)
+
+ result = grid.runOnce ()
+ button = buttons.buttonPressed(result)
+
+ if button == TEXT_BACK_CHECK:
+ return INSTALL_BACK
+
+ if kernelentry.value():
+ self.bl.args.set(string.strip(kernelentry.value()))
+ else:
+ self.bl.args.set("")
+
+ cdevs = []
+ if chandeventry1.value():
+ cdevs.append(string.strip(chandeventry1.value()))
+ if chandeventry2.value():
+ cdevs.append(string.strip(chandeventry2.value()))
+ self.bl.args.chandevset(cdevs)
+ return INSTALL_OK