diff options
author | wiktor w brodlo <wiktor@brodlo.net> | 2011-06-15 16:59:54 +0000 |
---|---|---|
committer | wiktor w brodlo <wiktor@brodlo.net> | 2011-06-15 16:59:54 +0000 |
commit | 2590d96369d0217e31dc2812690dde61dac417b5 (patch) | |
tree | 82276f787b08a28548e342c7921486f1acefab9f /textw | |
parent | first commit (diff) | |
download | anaconda-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.am | 24 | ||||
-rw-r--r-- | textw/complete_text.py | 65 | ||||
-rw-r--r-- | textw/constants_text.py | 68 | ||||
-rw-r--r-- | textw/keyboard_text.py | 67 | ||||
-rw-r--r-- | textw/language_text.py | 70 | ||||
-rw-r--r-- | textw/netconfig_text.py | 285 | ||||
-rw-r--r-- | textw/network_text.py | 33 | ||||
-rw-r--r-- | textw/partition_text.py | 321 | ||||
-rw-r--r-- | textw/progress_text.py | 142 | ||||
-rw-r--r-- | textw/statusline_text.py | 78 | ||||
-rw-r--r-- | textw/task_text.py | 28 | ||||
-rw-r--r-- | textw/timezone_text.py | 131 | ||||
-rw-r--r-- | textw/upgrade_bootloader_text.py | 183 | ||||
-rw-r--r-- | textw/upgrade_text.py | 258 | ||||
-rw-r--r-- | textw/userauth_text.py | 238 | ||||
-rw-r--r-- | textw/welcome_text.py | 47 | ||||
-rw-r--r-- | textw/zipl_text.py | 102 |
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 |