[PATCH] Add the "Add FCoE" dialog.

Chris Lumens clumens at redhat.com
Mon Apr 22 15:21:49 UTC 2013


---
 po/POTFILES.in                                 |   1 +
 pyanaconda/constants.py                        |   1 +
 pyanaconda/ui/gui/spokes/advstorage/fcoe.glade | 268 +++++++++++++++++++++++++
 pyanaconda/ui/gui/spokes/advstorage/fcoe.py    | 121 +++++++++++
 pyanaconda/ui/gui/spokes/filter.py             |  15 +-
 5 files changed, 405 insertions(+), 1 deletion(-)
 create mode 100644 pyanaconda/ui/gui/spokes/advstorage/fcoe.glade
 create mode 100644 pyanaconda/ui/gui/spokes/advstorage/fcoe.py

diff --git a/po/POTFILES.in b/po/POTFILES.in
index 695be87..3b369c3 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -89,6 +89,7 @@ pyanaconda/ui/gui/spokes/source.glade
 pyanaconda/ui/gui/spokes/welcome.glade
 pyanaconda/ui/gui/spokes/user.glade
 pyanaconda/ui/gui/spokes/custom.glade
+pyanaconda/ui/gui/spokes/advstorage/fcoe.glade
 pyanaconda/ui/gui/spokes/advstorage/iscsi.glade
 pyanaconda/ui/gui/spokes/lib/cart.glade
 pyanaconda/ui/gui/spokes/lib/detailederror.glade
diff --git a/pyanaconda/constants.py b/pyanaconda/constants.py
index 4c587d1..7adb9b6 100644
--- a/pyanaconda/constants.py
+++ b/pyanaconda/constants.py
@@ -122,6 +122,7 @@ THREAD_CHECK_SOFTWARE = "AnaCheckSoftwareThread"
 THREAD_SOURCE_WATCHER = "AnaSourceWatcher"
 THREAD_INSTALL = "AnaInstallThread"
 THREAD_CONFIGURATION = "AnaConfigurationThread"
+THREAD_FCOE = "AnaFCOEThread"
 THREAD_ISCSI_DISCOVER = "AnaIscsiDiscoverThread"
 THREAD_ISCSI_LOGIN = "AnaIscsiLoginThread"
 THREAD_GEOLOCATION_REFRESH = "AnaGeolocationRefreshThread"
diff --git a/pyanaconda/ui/gui/spokes/advstorage/fcoe.glade b/pyanaconda/ui/gui/spokes/advstorage/fcoe.glade
new file mode 100644
index 0000000..a8ad147
--- /dev/null
+++ b/pyanaconda/ui/gui/spokes/advstorage/fcoe.glade
@@ -0,0 +1,268 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+  <!-- interface-requires gtk+ 3.0 -->
+  <object class="GtkDialog" id="fcoeDialog">
+    <property name="can_focus">False</property>
+    <property name="border_width">5</property>
+    <property name="resizable">False</property>
+    <property name="modal">True</property>
+    <property name="type_hint">dialog</property>
+    <property name="decorated">False</property>
+    <child internal-child="vbox">
+      <object class="GtkBox" id="dialog-vbox1">
+        <property name="can_focus">False</property>
+        <property name="orientation">vertical</property>
+        <property name="spacing">2</property>
+        <child internal-child="action_area">
+          <object class="GtkButtonBox" id="dialog-action_area1">
+            <property name="can_focus">False</property>
+            <property name="layout_style">end</property>
+            <child>
+              <object class="GtkButton" id="cancelButton">
+                <property name="label">gtk-cancel</property>
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">True</property>
+                <property name="use_stock">True</property>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">True</property>
+                <property name="position">0</property>
+              </packing>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="pack_type">end</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkGrid" id="grid1">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="row_spacing">6</property>
+            <property name="column_spacing">6</property>
+            <child>
+              <object class="GtkLabel" id="label1">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="margin_bottom">6</property>
+                <property name="xalign">0</property>
+                <property name="label" translatable="yes">Please select the network interface which is connected to your FCoE switch.</property>
+                <property name="wrap">True</property>
+              </object>
+              <packing>
+                <property name="left_attach">0</property>
+                <property name="top_attach">0</property>
+                <property name="width">2</property>
+                <property name="height">1</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkLabel" id="label2">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="xalign">0</property>
+                <property name="label" translatable="yes">_NIC:</property>
+                <property name="use_underline">True</property>
+                <property name="mnemonic_widget">nicCombo</property>
+              </object>
+              <packing>
+                <property name="left_attach">0</property>
+                <property name="top_attach">1</property>
+                <property name="width">1</property>
+                <property name="height">1</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkComboBoxText" id="nicCombo">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="hexpand">True</property>
+                <property name="entry_text_column">0</property>
+                <property name="id_column">1</property>
+              </object>
+              <packing>
+                <property name="left_attach">1</property>
+                <property name="top_attach">1</property>
+                <property name="width">1</property>
+                <property name="height">1</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkCheckButton" id="dcbCheckbox">
+                <property name="label" translatable="yes">Use _DCB</property>
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">False</property>
+                <property name="use_underline">True</property>
+                <property name="xalign">0</property>
+                <property name="draw_indicator">True</property>
+              </object>
+              <packing>
+                <property name="left_attach">0</property>
+                <property name="top_attach">2</property>
+                <property name="width">2</property>
+                <property name="height">1</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkCheckButton" id="autoCheckbox">
+                <property name="label" translatable="yes">Use auto _vlan</property>
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">False</property>
+                <property name="use_underline">True</property>
+                <property name="xalign">0</property>
+                <property name="active">True</property>
+                <property name="draw_indicator">True</property>
+              </object>
+              <packing>
+                <property name="left_attach">0</property>
+                <property name="top_attach">3</property>
+                <property name="width">2</property>
+                <property name="height">1</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkBox" id="box1">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="spacing">6</property>
+                <child>
+                  <object class="GtkSpinner" id="addSpinner">
+                    <property name="can_focus">False</property>
+                    <property name="no_show_all">True</property>
+                    <property name="halign">end</property>
+                    <property name="hexpand">True</property>
+                    <property name="active">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="addButton">
+                    <property name="label" translatable="yes">_Add FCoE Disk(s)</property>
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="receives_default">True</property>
+                    <property name="use_underline">True</property>
+                    <signal name="clicked" handler="on_add_clicked" swapped="no"/>
+                  </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="fill">True</property>
+                    <property name="pack_type">end</property>
+                    <property name="position">1</property>
+                  </packing>
+                </child>
+              </object>
+              <packing>
+                <property name="left_attach">1</property>
+                <property name="top_attach">4</property>
+                <property name="width">1</property>
+                <property name="height">1</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkGrid" id="errorBox">
+                <property name="can_focus">False</property>
+                <property name="no_show_all">True</property>
+                <property name="row_spacing">6</property>
+                <property name="column_spacing">6</property>
+                <child>
+                  <object class="GtkImage" id="image1">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="xalign">1</property>
+                    <property name="stock">gtk-dialog-error</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="label3">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="xalign">0</property>
+                    <property name="label" translatable="yes">&lt;b&gt;Error adding FCoE SAN.&lt;/b&gt;</property>
+                    <property name="use_markup">True</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="errorLabel">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="xalign">0</property>
+                    <property name="label">Error message goes here.</property>
+                    <property name="wrap">True</property>
+                  </object>
+                  <packing>
+                    <property name="left_attach">1</property>
+                    <property name="top_attach">2</property>
+                    <property name="width">1</property>
+                    <property name="height">1</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkLabel" id="label4">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="xalign">0</property>
+                    <property name="label" translatable="yes">The following error occurred while attempting to add an FCoE SAN.  Please check your configuration and try again</property>
+                    <property name="wrap">True</property>
+                  </object>
+                  <packing>
+                    <property name="left_attach">1</property>
+                    <property name="top_attach">1</property>
+                    <property name="width">1</property>
+                    <property name="height">1</property>
+                  </packing>
+                </child>
+                <child>
+                  <placeholder/>
+                </child>
+                <child>
+                  <placeholder/>
+                </child>
+              </object>
+              <packing>
+                <property name="left_attach">0</property>
+                <property name="top_attach">5</property>
+                <property name="width">2</property>
+                <property name="height">1</property>
+              </packing>
+            </child>
+            <child>
+              <placeholder/>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="position">1</property>
+          </packing>
+        </child>
+      </object>
+    </child>
+    <action-widgets>
+      <action-widget response="0">cancelButton</action-widget>
+    </action-widgets>
+  </object>
+</interface>
diff --git a/pyanaconda/ui/gui/spokes/advstorage/fcoe.py b/pyanaconda/ui/gui/spokes/advstorage/fcoe.py
new file mode 100644
index 0000000..9617f6d
--- /dev/null
+++ b/pyanaconda/ui/gui/spokes/advstorage/fcoe.py
@@ -0,0 +1,121 @@
+# FCoE configuration dialog
+#
+# Copyright (C) 2013  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): Chris Lumens <clumens at redhat.com>
+#
+
+# pylint: disable-msg=E0611
+from gi.repository import GLib, Gtk
+
+from pyanaconda import constants
+from pyanaconda.threads import threadMgr, AnacondaThread
+from pyanaconda.ui.gui import GUIObject
+from pyanaconda import nm
+
+import gettext
+_ = lambda x: gettext.ldgettext("anaconda", x)
+
+__all__ = ["FCoEDialog"]
+
+class FCoEDialog(GUIObject):
+    builderObjects = ["fcoeDialog"]
+    mainWidgetName = "fcoeDialog"
+    uiFile = "spokes/advstorage/fcoe.glade"
+
+    def __init__(self, data, storage):
+        GUIObject.__init__(self, data)
+
+        self._addError = None
+
+        self.storage = storage
+        self.fcoe = self.storage.fcoe()
+
+    def refresh(self):
+        self._addButton = self.builder.get_object("addButton")
+        self._cancelButton = self.builder.get_object("cancelButton")
+        self._addSpinner = self.builder.get_object("addSpinner")
+        self._errorBox = self.builder.get_object("errorBox")
+
+        self._nicCombo = self.builder.get_object("nicCombo")
+        self._nicCombo.remove_all()
+
+        for devname in nm.nm_devices():
+            if not nm.nm_device_type_is_ethernet(devname):
+                continue
+
+            self._nicCombo.append_text("%s - %s" % (devname, nm.nm_device_hwaddress(devname)))
+
+        self._nicCombo.set_active(0)
+
+    def run(self):
+        rc = self.window.run()
+        self.window.destroy()
+        return rc
+
+    @property
+    def nic(self):
+        text = self._nicCombo.get_active_text()
+        return text.split()[0]
+
+    @property
+    def use_dcb(self):
+        return self.builder.get_object("dcbCheckbox").get_active()
+
+    @property
+    def use_auto_vlan(self):
+        return self.builder.get_object("autoCheckbox").get_active()
+
+    def _add(self):
+        try:
+            self.fcoe.addSan(self.nic, self.use_dcb, self.use_auto_vlan)
+        except Exception as e:
+            self._addError = str(e)
+
+    def _check_add(self, *args):
+        if threadMgr.get(constants.THREAD_FCOE):
+            return True
+
+        # When fcoe discovery is done, update the UI.  We don't need to worry
+        # about the user escaping from the dialog because all the buttons are
+        # marked insensitive.
+        self._addSpinner.stop()
+        self._addSpinner.hide()
+
+        if self._addError:
+            # Failure.  Display some error message and leave the user on the
+            # dialog to try again.
+            self.builder.getObject("errorLabel").set_text(self._addError)
+            self._addError = None
+            self._addButton.set_sensitive(True)
+            self._cancelButton.set_sensitive(True)
+        else:
+            # Success.  There's nothing else the user can do on this dialog.
+            self.window.response(1)
+
+    def on_add_clicked(self, *args):
+        # Set some widgets to visible/not while we work.
+        self._errorBox.hide()
+        self._addButton.set_sensitive(False)
+        self._cancelButton.set_sensitive(False)
+        self._addSpinner.set_visible(True)
+        self._addSpinner.show()
+
+        self._addSpinner.start()
+
+        threadMgr.add(AnacondaThread(name=constants.THREAD_FCOE, target=self._add))
+        GLib.timeout_add(250, self._check_add)
diff --git a/pyanaconda/ui/gui/spokes/filter.py b/pyanaconda/ui/gui/spokes/filter.py
index 199c8b0..c6840e6 100644
--- a/pyanaconda/ui/gui/spokes/filter.py
+++ b/pyanaconda/ui/gui/spokes/filter.py
@@ -29,12 +29,14 @@ import itertools
 
 from blivet import arch
 from blivet.devices import DASDDevice, FcoeDiskDevice, iScsiDiskDevice, MultipathDevice, MDRaidArrayDevice, ZFCPDiskDevice
+from blivet.fcoe import has_fcoe
 
 from pyanaconda.flags import flags
 
 from pyanaconda.ui.lib.disks import getDisks, isLocalDisk, size_str
 from pyanaconda.ui.gui.utils import enlightbox
 from pyanaconda.ui.gui.spokes import NormalSpoke
+from pyanaconda.ui.gui.spokes.advstorage.fcoe import FCoEDialog
 from pyanaconda.ui.gui.spokes.advstorage.iscsi import ISCSIDialog
 from pyanaconda.ui.gui.spokes.lib.cart import SelectedDisksDialog
 from pyanaconda.ui.gui.categories.storage import StorageCategory
@@ -441,6 +443,9 @@ class FilterSpoke(NormalSpoke):
             self._notebook.remove_page(-1)
             self.builder.get_object("addZFCPButton").destroy()
 
+        if not has_fcoe():
+            self.builder.get_object("addFCOEButton").destroy()
+
         self._store = self.builder.get_object("diskStore")
         self._addDisksButton = self.builder.get_object("addDisksButton")
 
@@ -568,7 +573,15 @@ class FilterSpoke(NormalSpoke):
         self.refresh()
 
     def on_add_fcoe_clicked(self, widget, *args):
-        pass
+        dialog = FCoEDialog(self.data, self.storage)
+
+        with enlightbox(self.window, dialog.window):
+            dialog.refresh()
+            dialog.run()
+
+        # We now need to refresh so any new disks picked up by adding advanced
+        # storage are displayed in the UI.
+        self.refresh()
 
     def on_add_zfcp_clicked(self, widget, *args):
         pass
-- 
1.8.1.2



More information about the anaconda-patches mailing list