From fa6d46fe60f199bfad4e7d53e3c07c280d7d4466 Mon Sep 17 00:00:00 2001 From: Karsten Hopp Date: Mon, 2 Aug 2004 13:09:35 +0000 Subject: The main zfcp stuff, initial versions --- iw/zfcp_gui.py | 276 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ zfcp.py | 150 +++++++++++++++++++++++++++++++ 2 files changed, 426 insertions(+) create mode 100644 iw/zfcp_gui.py create mode 100644 zfcp.py diff --git a/iw/zfcp_gui.py b/iw/zfcp_gui.py new file mode 100644 index 000000000..b180f8a6e --- /dev/null +++ b/iw/zfcp_gui.py @@ -0,0 +1,276 @@ +# +# zfcp_gui.py: mainframe FCP configuration dialog +# +# Karsten Hopp +# +# Copyright 2000-2004 Red Hat, Inc. +# +# This software may be freely redistributed under the terms of the GNU +# library public license. +# +# You should have received a copy of the GNU Library Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +# +import gtk +import gobject +from iw_gui import * +import gui +from rhpl.translate import _, N_ +import os +import isys + +class ZFCPWindow(InstallWindow): + + windowTitle = N_("ZFCP Configuration") + htmlTag = "zfcpconf" + + def __init__(self, ics): + InstallWindow.__init__(self, ics) + self.options = [(_("Device number"), 1, self.handleInvalidDevice), + (_("SCSI Id"), 0, self.handleInvalidSCSIId), + (_("WWPN"), 1, self.handleInvalidWWPN), + (_("SCSI LUN"), 0, self.handleInvalidSCSILun), + (_("FCP LUN"), 1, self.handleInvalidFCPLun)] + + def getNext(self): + self.fcp.writeFcpSysfs(self.fcpdevices) + isys.flushDriveDict() + self.diskset.refreshDevices(self.intf) + try: + iutil.makeDriveDeviceNodes() + except: + pass + + def handleInvalidDevice(self): + self.intf.messageWindow(_("Error With Data"), + _("You have not specified a device number or the number is invalid")) + + def handleInvalidSCSIId(self): + self.intf.messageWindow(_("Error With Data"), + _("You have not specified a SCSI ID or the ID is invalid.")) + + def handleInvalidWWPN(self): + self.intf.messageWindow(_("Error With Data"), + _("You have not specified a worldwide port name or the name is invalid.")) + + def handleInvalidSCSILun(self): + self.intf.messageWindow(_("Error With Data"), + _("You have not specified a SCSI LUN or the number is invalid.")) + + def handleInvalidFCPLun(self): + self.intf.messageWindow(_("Error With Data"), + _("You have not specified a FCP LUN or the number is invalid.")) + + def setupDevices(self): + self.store = gtk.TreeStore(gobject.TYPE_STRING, + gobject.TYPE_STRING, + gobject.TYPE_STRING, + gobject.TYPE_STRING, + gobject.TYPE_STRING) + + self.view = gtk.TreeView(self.store) + for i in range(len(self.options)): + if self.options[i][1] == 1: + renderer = gtk.CellRendererText() + column = gtk.TreeViewColumn(self.options[i][0], renderer, text=i) + column.set_clickable(gtk.FALSE) + column.set_min_width(140) + column.set_sizing (gtk.TREE_VIEW_COLUMN_AUTOSIZE) + self.view.append_column(column) + for i in range(len(self.fcpdevices)): + self.store.append(None, (self.fcpdevices[i][0],self.fcpdevices[i][1], \ + self.fcpdevices[i][2],self.fcpdevices[i][3],self.fcpdevices[i][4])) + + self.ignoreEvents = 1 + iter = self.store.get_iter_first() + selection = self.view.get_selection() + selection.set_mode(gtk.SELECTION_BROWSE) + if iter != None: + selection.select_iter(iter) + self.ignoreEvents = 0 + return self.view + + + # ZFCPWindow tag="zfcpconf" + def getScreen(self, fcp, diskset, intf): + self.diskset = diskset + self.intf = intf + box = gtk.VBox(gtk.FALSE) + box.set_border_width(6) + fcp.cleanFcpSysfs(fcp.fcpdevices) + self.fcp = fcp + self.fcpdevices = fcp.fcpdevices + + devvbox = gtk.VBox(gtk.FALSE) + + self.devlist = self.setupDevices() + + devlistSW = gtk.ScrolledWindow() + devlistSW.set_border_width(6) + devlistSW.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC) + devlistSW.set_shadow_type(gtk.SHADOW_IN) + devlistSW.add(self.devlist) + devlistSW.set_size_request(-1, 350) + devvbox.pack_start(devlistSW, gtk.FALSE, padding=10) + + buttonbar = gtk.HButtonBox() + buttonbar.set_layout(gtk.BUTTONBOX_START) + buttonbar.set_border_width(6) + add = gtk.Button(_("_Add")) + add.connect("clicked", self.addDevice) + buttonbar.pack_start(add, gtk.FALSE) + edit = gtk.Button(_("_Edit")) + edit.connect("clicked", self.editDevice) + buttonbar.pack_start(edit, gtk.FALSE) + remove = gtk.Button(_("_Remove")) + remove.connect("clicked", self.removeDevice) + buttonbar.pack_start(remove, gtk.FALSE) + devvbox.pack_start(buttonbar, gtk.FALSE) + + devvbox.set_border_width(12) + l = gtk.Label() + l.set_markup("%s" %(_("FCP Devices"),)) + frame=gtk.Frame() + frame.set_label_widget(l) + frame.add(devvbox) + frame.set_shadow_type(gtk.SHADOW_NONE) + box.pack_start(frame, gtk.FALSE) + return box + + + def addDevice(self, data): + if self.ignoreEvents: + return + addWin = gtk.Dialog(_("Add FCP device"), + flags=gtk.DIALOG_MODAL) + gui.addFrame(addWin) + addWin.set_modal(gtk.TRUE) + addWin.set_position (gtk.WIN_POS_CENTER) + devbox = gtk.VBox() + fcpTable = gtk.Table(len(self.options), 2) + entrys = {} + for t in range(len(self.options)): + label = gtk.Label("%s:" %(self.options[t][0],)) + label.set_alignment(0.0, 0.5) + label.set_property("use-underline", gtk.TRUE) + fcpTable.attach(label, 0, 1, t, t+1, gtk.FILL, 0, 10) + entrys[t] = gtk.Entry(18) + fcpTable.attach(entrys[t], 1, 2, t, t+1, gtk.FILL, 0, 10) + + devbox.pack_start(fcpTable, gtk.FALSE, gtk.FALSE, 6) + devbox.set_border_width(6) + frame = gtk.Frame() + frame.set_border_width(12) + frame.add(devbox) + frame.set_shadow_type(gtk.SHADOW_NONE) + addWin.vbox.pack_start(frame, padding=6) + addWin.set_position(gtk.WIN_POS_CENTER) + addWin.show_all() + addWin.add_button('gtk-cancel', 2) + addWin.add_button('gtk-ok', 1) + tmpvals = {} + while 1: + invalid = 0 + rc = addWin.run() + if rc == 1: + for t in range(len(self.options)): + tmpvals[t] = entrys[t].get_text() + if tmpvals[t] == "": + self.options[t][2]() # FIXME: This hides addWin behind the main window + invalid = 1 + break + if t != 0 and tmpvals[t][:2] != "0x": + tmpvals[t] = "0x" + tmpvals[t] + elif t == 0: + tmpvals[t] = "0" * (4 - len(tmpvals[t])) + tmpvals[t] + if tmpvals[t][:4] != "0.0.": + tmpvals[t] = "0.0." + tmpvals[t] + + if invalid == 0: + addWin.destroy() + tmpvals[4] = self.fcp.expandLun(tmpvals[4]) + line = self.store.append(None, (tmpvals[0],tmpvals[1],tmpvals[2],tmpvals[3],tmpvals[4])) + self.fcpdevices.append(tmpvals) + break + if rc == 2: + addWin.destroy() + break + return + + def editDevice(self, data): + if self.ignoreEvents: + return + selection = self.view.get_selection() + (model, iter) = selection.get_selected() + if not iter: + return None + devicenum = model.get_value(iter, 0) + scsiid = model.get_value(iter, 1) + wwpn = model.get_value(iter, 2) + scsilun = model.get_value(iter, 3) + fcplun = model.get_value(iter, 4) + + # create dialog box + editWin = gtk.Dialog(_("Edit FCP device %s") % (devicenum,), + flags=gtk.DIALOG_MODAL) + gui.addFrame(editWin) + editWin.set_modal(gtk.TRUE) + editWin.set_position (gtk.WIN_POS_CENTER) + devbox = gtk.VBox() + fcpTable = gtk.Table(len(self.options), 2) + entrys = {} + for t in range(len(self.options)): + label = gtk.Label("%s:" %(self.options[t][0],)) + label.set_alignment(0.0, 0.5) + label.set_property("use-underline", gtk.TRUE) + fcpTable.attach(label, 0, 1, t, t+1, gtk.FILL, 0, 10) + entrys[t] = gtk.Entry(18) + entrys[t].set_text(model.get_value(iter, t)) + fcpTable.attach(entrys[t], 1, 2, t, t+1, gtk.FILL, 0, 10) + devbox.pack_start(fcpTable, gtk.FALSE, gtk.FALSE, 6) + devbox.set_border_width(6) + frame = gtk.Frame() + frame.set_border_width(12) + frame.add(devbox) + frame.set_shadow_type(gtk.SHADOW_NONE) + editWin.vbox.pack_start(frame, padding=6) + editWin.set_position(gtk.WIN_POS_CENTER) + editWin.show_all() + editWin.add_button('gtk-cancel', 2) + editWin.add_button('gtk-ok', 1) + tmpvals = {} + while 1: + invalid = 0 + rc = editWin.run() + if rc == 2: + editWin.destroy() + return + if rc == 1: + for t in range(len(self.options)): + tmpvals[t] = entrys[t].get_text() + if tmpvals[t] == "": + self.options[t][2]() # FIXME: This hides addWin behind the main window + invalid = 1 + break + if invalid == 0: + editWin.destroy() + for t in range(len(self.options)): + self.store.set_value(iter, t, tmpvals[t]) + break + return + + def removeDevice(self, data): + selection = self.view.get_selection() + (model, iter) = selection.get_selected() + if not iter: + return None + rc = self.intf.messageWindow(_("Warning"), + _("You're about to remove a FCP disk from your " + "configuration. Are you sure that you wish " + "to continue?"), type = "yesno") + if rc == 1: + self.store.remove(iter) + return + +# vim:tw=78:ts=4:et:sw=4 diff --git a/zfcp.py b/zfcp.py new file mode 100644 index 000000000..8f0501b39 --- /dev/null +++ b/zfcp.py @@ -0,0 +1,150 @@ +# +# zfcp.py - mainframe zfcp configuration install data +# +# Karsten Hopp +# +# Copyright 2001-2004 Red Hat, Inc. +# +# This software may be freely redistributed under the terms of the GNU +# library public license. +# +# You should have received a copy of the GNU Library Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +# + +import string +import os +import iutil + +from rhpl.translate import _, N_ +from rhpl.log import log + + +class ZFCP: + def __init__(self): + self.readConfig() + + # remove the configuration from sysfs, required when the user + # steps backward from the partitioning screen and changes fcp configuration + def cleanFcpSysfs(self, fcpdevices): + if not len(fcpdevices): + return + on = "/sys/bus/ccw/drivers/zfcp/%s/online" + pr = "/sys/bus/ccw/drivers/zfcp/%s/port_remove" + ur = "/sys/bus/ccw/drivers/zfcp/%s/%s/unit_remove" + for i in range(len(fcpdevices)): + fno = on % (fcpdevices[i][0],) + fnp = pr % (fcpdevices[i][0],) + fnu = ur % (fcpdevices[i][0],fcpdevices[i][2],) + try: + fo = open(fno, "w") + log("echo %s > %s" % (0, fno)) + fo.write("0") + fo.close() + try: + fu = open(fnu, "w") + log("echo %s > %s" % (fcpdevices[i][4], fnu)) + fu.write("%s\n" % (fcpdevices[i][4],)) + fu.close() + try: + fp = open(fnp, "w") + log("echo %s > %s" % (fcpdevices[i][2], fnp)) + fp.write("%s\n" % (fcpdevices[i][2],)) + fp.close() + except: + continue + except: + continue + except: + continue + + # initialize devices via sysfs + def writeFcpSysfs(self,fcpdevices): + if not len(fcpdevices): + return + on = "/sys/bus/ccw/drivers/zfcp/%s/online" + pa = "/sys/bus/ccw/drivers/zfcp/%s/port_add" + ua = "/sys/bus/ccw/drivers/zfcp/%s/%s/unit_add" + for i in range(len(fcpdevices)): + fno = on % (fcpdevices[i][0],) + fnp = pa % (fcpdevices[i][0],) + fnu = ua % (fcpdevices[i][0],fcpdevices[i][2],) + try: + fp = open(fnp, "w") + log("echo %s > %s" % (fcpdevices[i][2], fnp)) + fp.write("%s\n" % (fcpdevices[i][2],)) + fp.close() + try: + fu = open(fnu, "w") + log("echo %s > %s" % (fcpdevices[i][4], fnu)) + fu.write("%s\n" % (fcpdevices[i][4],)) + fu.close() + try: + fo = open(fno, "w") + log("echo %s > %s" % (1, fno)) + fo.write("1") + fo.close() + except: + continue + except: + continue + except: + continue + + def write(self, instPath): + if not len(self.fcpdevices): + return + if not os.path.isdir("%s/etc/" %(instPath,)): + iutil.mkdirChain("%s/etc/" %(instPath,)) + + fn = "%s/etc/zfcp.conf" % (instPath,) + f = open(fn, "w") + os.chmod(fn, 0644) + for dev in self.fcpdevices: + f.write("%s %s %s %s %s\n" % (dev[0], dev[1], dev[2], dev[3], dev[4],)) + f.close() + + def writeKS(self,fcpdevices): + # FIXME KH not implemented yet + return + + def readConfig(self): + self.fcpdevices = [] + try: + f = open("/tmp/fcpconfig", "r") + except: + pass + else: + lines = f.readlines() + f.close() + for line in lines: + line = string.strip(line) + fcpconf = string.split(line) + if len(line) > 0 and (len(fcpconf) != 5 or fcpconf[0][:1] == "#"): # nonempty but invalid line or comment + continue + for i in range(1,5): + if fcpconf[i][:2] != "0x": + fcpconf[i] = "0x" + fcpconf[i] + fcpconf[4] = self.expandLun(fcpconf[4]) + self.fcpdevices.append(fcpconf) + + def sanityCheckHexValue(self, length, value): + # FIXME: do a real checking if this is a valid hex value + if len(value) == length: + return None + else: + return _("Invalid input. Entered string must have %d characters") % length + + # ZFCP LUNs are usually entered as 16 bit, sysfs accepts only 64 bit + # (#125632), expand with zeroes if necessary + def expandLun(self, lun): + if lun[:2] == "0x": + lun = lun[2:] + lun = "0x" + "0" * (4 - len(lun)) + lun + length = len(lun) - 2 + lun = lun + "0" * (16 - len(lun) + 2) + return lun + + +# vim:tw=78:ts=4:et:sw=4 -- cgit