This UI is the screen that allows the user to select which devices will be
wiped during installation and which should just be mounted. It also allows
selecting which device the bootloader should be installed to.
---
dispatch.py | 1 +
gui.py | 1 +
installclass.py | 1 +
iw/cleardisks_gui.py | 163 +++++++++++++++++++++++++++
kickstart.py | 2 +
text.py | 1 +
ui/cleardisks.glade | 300 ++++++++++++++++++++++++++++++++++++++++++++++++++
upgrade.py | 1 +
8 files changed, 470 insertions(+), 0 deletions(-)
create mode 100644 iw/cleardisks_gui.py
create mode 100644 ui/cleardisks.glade
diff --git a/dispatch.py b/dispatch.py
index 5beb5bc..1335ba2 100644
--- a/dispatch.py
+++ b/dispatch.py
@@ -77,6 +77,7 @@ installSteps = [
("timezone", ),
("accounts", ),
("setuptime", setupTimezone, ),
+ ("cleardiskssel", ),
("parttype", ),
("autopartitionexecute", doAutoPartition, ),
("partition", ),
diff --git a/gui.py b/gui.py
index 4d9542c..af3af5f 100755
--- a/gui.py
+++ b/gui.py
@@ -66,6 +66,7 @@ stepToClass = {
"filter" : ("filter_gui", "FilterWindow"),
"zfcpconfig" : ("zfcp_gui", "ZFCPWindow"),
"partition" : ("partition_gui", "PartitionWindow"),
+ "cleardiskssel": ("cleardisks_gui", "ClearDisksWindow"),
"parttype" : ("autopart_type", "PartitionTypeWindow"),
"findinstall" : ("examine_gui", "UpgradeExamineWindow"),
"addswap" : ("upgrade_swap_gui", "UpgradeSwapWindow"),
diff --git a/installclass.py b/installclass.py
index 92c4acd..8cdb880 100644
--- a/installclass.py
+++ b/installclass.py
@@ -94,6 +94,7 @@ class BaseInstallClass(object):
"findrootparts",
"betanag",
"installtype",
+ "cleardiskssel",
"parttype",
"autopartitionexecute",
"partition",
diff --git a/iw/cleardisks_gui.py b/iw/cleardisks_gui.py
new file mode 100644
index 0000000..c6409ca
--- /dev/null
+++ b/iw/cleardisks_gui.py
@@ -0,0 +1,163 @@
+#
+# Select which disks to clear and which ones to just mount.
+#
+# Copyright (C) 2009 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 gtk, gobject
+import gui
+from DeviceSelector import *
+from constants import *
+from iw_gui import *
+from storage.udev import *
+
+import gettext
+_ = lambda x: gettext.ldgettext("anaconda", x)
+
+class ClearDisksWindow (InstallWindow):
+ windowTitle = N_("Clear Disks Selector")
+
+ def getNext (self):
+ # All the rows that are visible in the right hand side should be cleared.
+ cleardisks = []
+ for row in self.store:
+ if row[3]:
+ cleardisks.append(row[OBJECT_COL].name)
+
+ if len(cleardisks) == 0:
+ self.anaconda.intf.messageWindow(_("Error"),
+ _("You must select at least one "
+ "drive to be used for installation."),
+ custom_icon="error")
+ raise gui.StayOnScreen
+
+ # The selected row is the disk to boot from.
+ selected = self.rightDS.getSelected()
+
+ if len(selected) == 0:
+ self.anaconda.intf.messageWindow(_("Error"),
+ _("You must select one drive to "
+ "boot from."),
+ custom_icon="error")
+ raise gui.StayOnScreen
+
+ bootDisk = selected[0][OBJECT_COL].name
+
+ self.anaconda.id.storage.clearPartDisks.extend(cleardisks + [bootDisk])
+ self.anaconda.id.bootloader.drivelist = [bootDisk] + cleardisks
+
+ def getScreen (self, anaconda):
+ (xml, self.vbox) = gui.getGladeWidget("cleardisks.glade", "vbox")
+ self.leftScroll = xml.get_widget("leftScroll")
+ self.rightScroll = xml.get_widget("rightScroll")
+ self.addButton = xml.get_widget("addButton")
+ self.removeButton = xml.get_widget("removeButton")
+
+ self.anaconda = anaconda
+
+ # One store for both views. First the obejct, then a visible/active for
+ # the left hand side, then a visible/active for the right hand side, then
+ # all the other stuff.
+ self.store = gtk.TreeStore(gobject.TYPE_PYOBJECT,
+ gobject.TYPE_BOOLEAN, gobject.TYPE_BOOLEAN,
+ gobject.TYPE_BOOLEAN, gobject.TYPE_BOOLEAN,
+ gobject.TYPE_STRING, gobject.TYPE_STRING,
+ gobject.TYPE_STRING, gobject.TYPE_STRING,
+ gobject.TYPE_STRING)
+ self.store.set_sort_column_id(5, gtk.SORT_ASCENDING)
+
+ # The left view shows all the drives that will just be mounted, but
+ # can still be moved to the right hand side.
+ self.leftSortedModel = gtk.TreeModelSort(self.store)
+ self.leftFilteredModel = self.store.filter_new()
+ self.leftTreeView = gtk.TreeView(self.leftFilteredModel)
+
+ self.leftFilteredModel.set_visible_func(lambda model, iter, view: model.get_value(iter, 1), self.leftTreeView)
+
+ self.leftScroll.add(self.leftTreeView)
+
+ self.leftDS = DeviceSelector(self.store, self.leftFilteredModel,
+ self.leftTreeView, visible=1, active=2)
+ self.leftDS.createMenu()
+ self.leftDS.addColumn(_("Model"), 5)
+ self.leftDS.addColumn(_("Capacity"), 6)
+ self.leftDS.addColumn(_("Vendor"), 7)
+ self.leftDS.addColumn(_("Interconnect"), 8, displayed=False)
+ self.leftDS.addColumn(_("Serial Number"), 9, displayed=False)
+
+ # The right view show all the drives that will be wiped during install.
+ self.rightSortedModel = gtk.TreeModelSort(self.store)
+ self.rightFilteredModel = self.store.filter_new()
+ self.rightTreeView = gtk.TreeView(self.rightFilteredModel)
+
+ self.rightFilteredModel.set_visible_func(lambda model, iter, view: model.get_value(iter, 3), self.rightTreeView)
+
+ self.rightScroll.add(self.rightTreeView)
+
+ self.rightDS = DeviceSelector(self.store, self.rightFilteredModel,
+ self.rightTreeView, visible=3,
+ active=4)
+ self.rightDS.createSelectionCol(title=_("Boot"), radioButton=True)
+ self.rightDS.addColumn(_("Model"), 5)
+ self.rightDS.addColumn(_("Capacity"), 6)
+
+ # The device filtering UI set up exclusiveDisks as a list of the names
+ # of all the disks we should use later on. Now we need to go get those,
+ # look up some more information in the devicetree, and set up the
+ # selector.
+ for d in self.anaconda.id.storage.exclusiveDisks:
+ device = self.anaconda.id.storage.devicetree.getDeviceByName(d)
+ if not device:
+ continue
+
+ self.store.append(None, (device, True, True, False, False,
+ device.partedDevice.model,
+ str(int(device.size)) + " MB",
+ device.vendor, "", device.serial))
+
+ self.addButton.connect("clicked", self._add_clicked)
+ self.removeButton.connect("clicked", self._remove_clicked)
+
+ return self.vbox
+
+ def _add_clicked(self, button):
+ (filteredModel, filteredIter) = self.leftTreeView.get_selection().get_selected()
+
+ if not filteredIter:
+ return
+
+ sortedIter = self.leftFilteredModel.convert_iter_to_child_iter(filteredIter)
+
+ self.store.set_value(sortedIter, 1, False)
+ self.store.set_value(sortedIter, 3, True)
+
+ self.leftFilteredModel.refilter()
+ self.rightFilteredModel.refilter()
+
+ def _remove_clicked(self, button):
+ (filteredModel, filteredIter) = self.rightTreeView.get_selection().get_selected()
+
+ if not filteredIter:
+ return
+
+ sortedIter = self.rightFilteredModel.convert_iter_to_child_iter(filteredIter)
+
+ self.store.set_value(sortedIter, 1, True)
+ self.store.set_value(sortedIter, 3, False)
+
+ self.leftFilteredModel.refilter()
+ self.rightFilteredModel.refilter()
diff --git a/kickstart.py b/kickstart.py
index 147e48d..ee8a735 100644
--- a/kickstart.py
+++ b/kickstart.py
@@ -281,6 +281,7 @@ class ClearPart(commands.clearpart.FC3_ClearPart):
anaconda.id.storage.reinitializeDisks = self.initAll
clearPartitions(anaconda.id.storage)
+ self.handler.skipSteps.append("cleardisksel")
class FcoeData(commands.fcoe.F13_FcoeData):
def execute(self, anaconda):
@@ -1410,6 +1411,7 @@ def setSteps(anaconda):
if anaconda.id.displayMode == "t":
missingSteps = [("bootloader", "Bootloader configuration"),
("filter", "Disks to use in installation"),
+ ("cleardisksel", "Disks to clear"),
("group-selection", "Package selection")]
errors = []
diff --git a/text.py b/text.py
index 5b8900d..12eabbb 100644
--- a/text.py
+++ b/text.py
@@ -550,6 +550,7 @@ class InstallInterface:
def setSteps(self, anaconda):
anaconda.dispatch.skipStep("filter")
+ anaconda.dispatch.skipStep("cleardisksel")
anaconda.dispatch.skipStep("basepkgsel")
anaconda.dispatch.skipStep("group-selection")
diff --git a/ui/cleardisks.glade b/ui/cleardisks.glade
new file mode 100644
index 0000000..c6a1bac
--- /dev/null
+++ b/ui/cleardisks.glade
@@ -0,0 +1,300 @@
+<?xml version="1.0" standalone="no"?> <!--*- mode: xml -*-->
+<!DOCTYPE glade-interface SYSTEM "http://glade.gnome.org/glade-2.0.dtd">
+
+<glade-interface>
+
+<widget class="GtkWindow" id="cleardisksWindow">
+<property name="border_width">6</property>
+<property name="width_request">600</property>
+<property name="title" translatable="yes" context="yes"></property>
+<property name="type">GTK_WINDOW_TOPLEVEL</property>
+<property name="window_position">GTK_WIN_POS_NONE</property>
+<property name="modal">False</property>
+<property name="resizable">True</property>
+<property name="destroy_with_parent">False</property>
+<property name="decorated">True</property>
+<property name="skip_taskbar_hint">False</property>
+<property name="skip_pager_hint">False</property>
+<property name="type_hint">GDK_WINDOW_TYPE_HINT_NORMAL</property>
+<property name="gravity">GDK_GRAVITY_NORTH_WEST</property>
+<property name="focus_on_map">True</property>
+<property name="urgency_hint">False</property>
+
+<child>
+<widget class="GtkVBox" id="vbox">
+<property name="visible">True</property>
+<property name="homogeneous">False</property>
+<property name="spacing">12</property>
+
+<child>
+ <widget class="GtkLabel" id="label1">
+ <property name="width_request">600</property>
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Below are the storage devices you've selected to be a part of this installation. Please indicate using the arrows below which devices you'd like to use as data drives (these will not be formatted, only mounted) and which devices you'd like to use as storage for the install (these will be formatted).</property>
+ <property name="use_underline">False</property>
+ <property name="use_markup">False</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">True</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0</property>
+ <property name="yalign">0</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+ <property name="width_chars">-1</property>
+ <property name="single_line_mode">False</property>
+ <property name="angle">0</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+</child>
+
+<child>
+ <widget class="GtkHBox" id="hbox2">
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">6</property>
+
+ <child>
+ <widget class="GtkVBox" id="vbox1">
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">0</property>
+
+ <child>
+ <widget class="GtkLabel" id="label4">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes"><b>Data Storage Devices</b> (to be mounted only)</property>
+ <property name="use_underline">False</property>
+ <property name="use_markup">True</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+ <property name="width_chars">-1</property>
+ <property name="single_line_mode">False</property>
+ <property name="angle">0</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkScrolledWindow" id="leftScroll">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
+ <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
+ <property name="shadow_type">GTK_SHADOW_ETCHED_IN</property>
+ <property name="window_placement">GTK_CORNER_TOP_LEFT</property>
+
+ <child>
+ <placeholder/>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkVButtonBox" id="vbuttonbox1">
+ <property name="visible">True</property>
+ <property name="layout_style">GTK_BUTTONBOX_SPREAD</property>
+ <property name="spacing">0</property>
+
+ <child>
+ <widget class="GtkButton" id="addButton">
+ <property name="visible">True</property>
+ <property name="can_default">True</property>
+ <property name="can_focus">True</property>
+ <property name="relief">GTK_RELIEF_NORMAL</property>
+ <property name="focus_on_click">True</property>
+
+ <child>
+ <widget class="GtkImage" id="image3">
+ <property name="visible">True</property>
+ <property name="stock">gtk-go-forward</property>
+ <property name="icon_size">4</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ </child>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkButton" id="removeButton">
+ <property name="visible">True</property>
+ <property name="can_default">True</property>
+ <property name="can_focus">True</property>
+ <property name="relief">GTK_RELIEF_NORMAL</property>
+ <property name="focus_on_click">True</property>
+
+ <child>
+ <widget class="GtkImage" id="image2">
+ <property name="visible">True</property>
+ <property name="stock">gtk-go-back</property>
+ <property name="icon_size">4</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ </child>
+ </widget>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkVBox" id="vbox2">
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">0</property>
+
+ <child>
+ <widget class="GtkLabel" id="label5">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes"><b>Install Target Devices</b></property>
+ <property name="use_underline">False</property>
+ <property name="use_markup">True</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+ <property name="width_chars">-1</property>
+ <property name="single_line_mode">False</property>
+ <property name="angle">0</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkScrolledWindow" id="rightScroll">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
+ <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
+ <property name="shadow_type">GTK_SHADOW_ETCHED_IN</property>
+ <property name="window_placement">GTK_CORNER_TOP_LEFT</property>
+
+ <child>
+ <placeholder/>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ </packing>
+</child>
+
+<child>
+ <widget class="GtkHBox" id="hbox1">
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">0</property>
+
+ <child>
+ <widget class="GtkImage" id="image1">
+ <property name="visible">True</property>
+ <property name="stock">gtk-dialog-info</property>
+ <property name="icon_size">4</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkLabel" id="label3">
+ <property name="width_request">600</property>
+ <property name="visible">True</property>
+ <property name="label" translatable="yes"><b>Tip:</b> Install target devices will be reformatted and wiped of any data. Make sure you have backups.</property>
+ <property name="use_underline">False</property>
+ <property name="use_markup">True</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">True</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0</property>
+ <property name="yalign">0</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+ <property name="width_chars">-1</property>
+ <property name="single_line_mode">False</property>
+ <property name="angle">0</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+</child>
+</widget>
+</child>
+</widget>
+
+</glade-interface>
diff --git a/upgrade.py b/upgrade.py
index 99ae786..ede3de5 100644
--- a/upgrade.py
+++ b/upgrade.py
@@ -282,6 +282,7 @@ def setSteps(anaconda):
"keyboard",
"welcome",
"filter",
+ "cleardisksel",
"installtype",
"storageinit",
"findrootparts",