A GtkDialog box which shows the progress of dasdfmt as it is run against unformatted DASDs.
Resolves: rhbz#1064423 --- po/POTFILES.in | 2 + pyanaconda/ui/gui/spokes/lib/dasdfmt.glade | 211 +++++++++++++++++++++++++++++ pyanaconda/ui/gui/spokes/lib/dasdfmt.py | 111 +++++++++++++++ 3 files changed, 324 insertions(+) create mode 100644 pyanaconda/ui/gui/spokes/lib/dasdfmt.glade create mode 100644 pyanaconda/ui/gui/spokes/lib/dasdfmt.py
diff --git a/po/POTFILES.in b/po/POTFILES.in index 3d53ce4..4b341fc 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -76,6 +76,7 @@ pyanaconda/ui/gui/spokes/user.py pyanaconda/ui/gui/spokes/welcome.py pyanaconda/ui/gui/spokes/lib/accordion.py pyanaconda/ui/gui/spokes/lib/cart.py +pyanaconda/ui/gui/spokes/lib/dasdfmt.py pyanaconda/ui/gui/spokes/lib/passphrase.py pyanaconda/ui/gui/spokes/lib/refresh.py pyanaconda/ui/gui/spokes/lib/resize.py @@ -99,6 +100,7 @@ pyanaconda/ui/gui/spokes/advstorage/fcoe.glade pyanaconda/ui/gui/spokes/advstorage/iscsi.glade pyanaconda/ui/gui/spokes/advstorage/zfcp.glade pyanaconda/ui/gui/spokes/lib/cart.glade +pyanaconda/ui/gui/spokes/lib/dasdfmt.glade pyanaconda/ui/gui/spokes/lib/detailederror.glade pyanaconda/ui/gui/spokes/lib/passphrase.glade pyanaconda/ui/gui/spokes/lib/refresh.glade diff --git a/pyanaconda/ui/gui/spokes/lib/dasdfmt.glade b/pyanaconda/ui/gui/spokes/lib/dasdfmt.glade new file mode 100644 index 0000000..2fdb0c9 --- /dev/null +++ b/pyanaconda/ui/gui/spokes/lib/dasdfmt.glade @@ -0,0 +1,211 @@ +<?xml version="1.0" encoding="UTF-8"?> +<interface> + <!-- interface-requires gtk+ 3.6 --> + <object class="GtkDialog" id="unformattedDasdDialog"> + <property name="can_focus">False</property> + <property name="border_width">5</property> + <property name="title" translatable="yes">UNFORMATTED DASDS</property> + <property name="modal">True</property> + <property name="type_hint">dialog</property> + <property name="decorated">False</property> + <signal name="show" handler="dasdfmt" swapped="no"/> + <child internal-child="vbox"> + <object class="GtkBox" id="dialog-vbox1"> + <property name="can_focus">False</property> + <property name="orientation">vertical</property> + <property name="spacing">2</property> + <child> + <object class="GtkLabel" id="unformattedDasdsLabel"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="label" translatable="yes">Formatting DASDs</property> + <attributes> + <attribute name="weight" value="bold"/> + </attributes> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkNotebook" id="formatNotebook"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="show_tabs">False</property> + <child> + <placeholder/> + </child> + <child type="tab"> + <placeholder/> + </child> + <child> + <object class="GtkGrid" id="formatRunning"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="halign">center</property> + <property name="valign">center</property> + <property name="row_spacing">18</property> + <property name="column_spacing">6</property> + <child> + <object class="GtkSpinner" id="spinner4"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="active">True</property> + </object> + <packing> + <property name="left_attach">0</property> + <property name="top_attach">0</property> + <property name="width">1</property> + <property name="height">1</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="udLabel"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="label">Inform user which DASD is being formatted here.</property> + </object> + <packing> + <property name="left_attach">1</property> + <property name="top_attach">0</property> + <property name="width">1</property> + <property name="height">1</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="returnToHubLabel1"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="label" translatable="yes">You may <a href="">go back to the main menu</a> to complete other +installation options while this operation completes.</property> + <property name="use_markup">True</property> + <property name="wrap">True</property> + <property name="track_visited_links">False</property> + <signal name="activate-link" handler="return_to_hub_link_clicked" swapped="no"/> + </object> + <packing> + <property name="left_attach">0</property> + <property name="top_attach">1</property> + <property name="width">2</property> + <property name="height">1</property> + </packing> + </child> + </object> + <packing> + <property name="position">1</property> + </packing> + </child> + <child type="tab"> + <placeholder/> + </child> + <child> + <object class="GtkGrid" id="formatComplete"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="halign">center</property> + <property name="valign">center</property> + <property name="row_spacing">6</property> + <property name="column_spacing">6</property> + <child> + <object class="GtkImage" id="image3"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="stock">gtk-apply</property> + </object> + <packing> + <property name="left_attach">0</property> + <property name="top_attach">0</property> + <property name="width">1</property> + <property name="height">1</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="label19"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">Disk formatting complete.</property> + <property name="wrap">True</property> + <attributes> + <attribute name="weight" value="bold"/> + </attributes> + </object> + <packing> + <property name="left_attach">1</property> + <property name="top_attach">0</property> + <property name="width">1</property> + <property name="height">1</property> + </packing> + </child> + </object> + <packing> + <property name="position">2</property> + </packing> + </child> + <child type="tab"> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child type="tab"> + <placeholder/> + </child> + </object> + <packing> + <property name="expand">True</property> + <property name="fill">True</property> + <property name="position">3</property> + </packing> + </child> + <child internal-child="action_area"> + <object class="GtkButtonBox" id="dialog-action_area1"> + <property name="can_focus">False</property> + <property name="layout_style">end</property> + <child> + <object class="GtkButton" id="udCancelButton"> + <property name="label" translatable="yes">_Cancel</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <property name="use_underline">True</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkButton" id="udOKButton"> + <property name="label" translatable="yes">_OK</property> + <property name="visible">True</property> + <property name="sensitive">False</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <property name="use_underline">True</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="pack_type">end</property> + <property name="position">4</property> + </packing> + </child> + </object> + </child> + <action-widgets> + <action-widget response="0">udCancelButton</action-widget> + <action-widget response="1">udOKButton</action-widget> + </action-widgets> + </object> +</interface> diff --git a/pyanaconda/ui/gui/spokes/lib/dasdfmt.py b/pyanaconda/ui/gui/spokes/lib/dasdfmt.py new file mode 100644 index 0000000..802855c --- /dev/null +++ b/pyanaconda/ui/gui/spokes/lib/dasdfmt.py @@ -0,0 +1,111 @@ +# DASD format dialog +# +# Copyright (C) 2014 Red Hat, Inc. +# +# This copyrighted material is made available to anyone wishing to use, +# modify, copy, or redistribute it subject to the terms and conditions of +# the GNU General Public License v.2, or (at your option) any later version. +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY expressed or implied, including the implied warranties of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General +# Public License for more details. You should have received a copy of the +# GNU General Public License along with this program; if not, write to the +# Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +# 02110-1301, USA. Any Red Hat trademarks that are incorporated in the +# source code or documentation are not subject to the GNU General Public +# License and may only be used or replicated with the express permission of +# Red Hat, Inc. +# +# Red Hat Author(s): Samantha N. Bueno sbueno@redhat.com +# Chris Lumens clumens@redhat.com +# + +from pyanaconda.threads import threadMgr, AnacondaThread +from pyanaconda.ui.communication import hubQ +from pyanaconda.ui.gui import GUIObject +from pyanaconda.ui.gui.utils import gtk_call_once +from pyanaconda import constants +from pyanaconda.i18n import _ + +from blivet import storageInitialize +from blivet.devicelibs.dasd import format_dasd +from blivet.errors import DasdFormatError + +import logging +log = logging.getLogger("anaconda") + +__all__ = ["DasdFormatDialog"] + +class DasdFormatDialog(GUIObject): + builderObjects = ["unformattedDasdDialog"] + mainWidgetName = "unformattedDasdDialog" + uiFile = "spokes/lib/dasdfmt.glade" + + def __init__(self, data, storage, to_format): + GUIObject.__init__(self, data) + + self.storage = storage + self.to_format = to_format + + self._notebook = self.builder.get_object("formatNotebook") + self._cancel_button = self.builder.get_object("udCancelButton") + self._ok_button = self.builder.get_object("udOKButton") + self._label = self.builder.get_object("udLabel") + + def run(self): + rc = self.window.run() + self.window.destroy() + return rc + + def run_dasdfmt(self, *args): + """ + Loop through our disks and run dasdfmt against them. After that loop has + finished, launch stage two of this operation (finish_dasdfmt). + """ + for disk in self.to_format: + try: + self._label.set_text(_("Formatting /dev/%s. This may take a moment." % disk)) + format_dasd(disk) + except DasdFormatError as err: + # Log errors if formatting fails, but don't halt the installer + log.error(str(err)) + continue + + gtk_call_once(self.finish_dasdfmt) + + def dasdfmt(self, *args): + """ + This is the handler that gets called from the GtkDialog and sets things + in motion. We launch the *actual* call to run dasdfmt from a thread. + """ + # Run through all of the formatting + self._cancel_button.set_sensitive(True) + self._ok_button.set_sensitive(False) + self._notebook.set_current_page(0) + + # Loop through all of our unformatted DASDs and format them + threadMgr.add(AnacondaThread(name=constants.THREAD_DASDFMT, + target=self.run_dasdfmt, args=(self,))) + + def finish_dasdfmt(self): + """ + This is the second stage of the dasdfmt operation; now that formatting + is complete, we need to reinitialize storage so that the newly + formatted devices are added properly to the devicetree. + """ + protectedNames = map(lambda d: d.name, self.storage.protectedDevices) + threadMgr.add(AnacondaThread(name=constants.THREAD_STORAGE, target=storageInitialize, + args=(self.storage, self.data, protectedNames))) + + threadMgr.wait(constants.THREAD_STORAGE) + self._notebook.set_current_page(1) + self._ok_button.set_sensitive(True) + + def return_to_hub_link_clicked(self, label, uri): + """ + The user clicked on the link that takes them back to the hub. We need + to emit a special response ID indicating the user did not press OK. + + NOTE: There is no button with response_id=2. + """ + self.window.response(2)