FAQ Search Today's Posts Mark Forums Read
» Video Reviews

» Linux Archive

Linux-archive is a website aiming to archive linux email lists and to make them easily accessible for linux users/developers.


» Sponsor

» Partners

» Sponsor

Go Back   Linux Archive > Ubuntu > Ubuntu Development

 
 
LinkBack Thread Tools
 
Old 02-03-2009, 08:03 AM
Hans de Goede
 
Default Rewrite iscsi code using libiscsi

Hi All,

This patch replaces the iscsi.py code with new code using libiscsi, getting
rid of the awefull configfile mangling to set auth info hack, and in general
making it much cleaner.

Fixes:
-Report error when we cannot add a disk instead of silently failing (461830)
-Report error when trying to use iscsi from kickstart without having an
iscsiname directive first (463156)
-Better feedback while scanning iscsi disks
-Make ibft work with chap and 2-way chap
-Make ibft configured disks available for upgrades and in rescue mode
-Make ibft boot work even when iscsi-initiator-utils is installed after the
kernel in the transaction

Note:
libiscsi is available in Fedora now
---
backend.py | 11 +
iscsi.py | 521 +++++++++++------------------------------------
iw/autopart_type.py | 7 +-
kickstart.py | 3 -
partitions.py | 3 +
rescue.py | 1 +
scripts/upd-instroot | 2 +
textw/partition_text.py | 2 +-
upgrade.py | 3 +
9 files changed, 148 insertions(+), 405 deletions(-)

diff --git a/backend.py b/backend.py
index 3008671..06f6c2b 100644
--- a/backend.py
+++ b/backend.py
@@ -79,9 +79,20 @@ class AnacondaBackend:
log.error("Could not copy firmware file %s: %s" % (f,
e.strerror))


def doPostInstall(self, anaconda):
+ has_iscsi_disk = False
+
+ # See if we have an iscsi disk. If we do we rerun mkinitrd, as
+ # the initrd might need iscsi-initiator-utils, and chances are
+ # it was not installed yet the first time mkinitrd was run, as
+ # mkinitrd does not require it.
+ for disk in anaconda.id.diskset.disks.keys():
+ if isys.driveIsIscsi(disk):
+ has_iscsi_disk = True
+
if anaconda.id.extraModules:
self.copyFirmware(anaconda)

+ if anaconda.id.extraModules or has_iscsi_disk:
for (n, arch, tag) in self.kernelVersionList(anaconda.rootPath):
packages.recreateInitrd(n, anaconda.rootPath)

diff --git a/iscsi.py b/iscsi.py
index a4d301e..24f7090 100644
--- a/iscsi.py
+++ b/iscsi.py
@@ -36,6 +36,11 @@ log = logging.getLogger("anaconda")
import gettext
_ = lambda x: gettext.ldgettext("anaconda", x)

+has_libiscsi = True
+try:
+ import libiscsi
+except:
+ has_libiscsi = False

# Note that stage2 copies all files under /sbin to /usr/sbin
global ISCSID
@@ -43,7 +48,6 @@ ISCSID=""
global ISCSIADM
ISCSIADM = ""
INITIATOR_FILE="/etc/iscsi/initiatorname.iscsi"
-ISCSID_CONF="/etc/iscsi/iscsid.conf"

def find_iscsi_files():
global ISCSID
@@ -61,7 +65,7 @@ def find_iscsi_files():

def has_iscsi():
find_iscsi_files()
- if ISCSID == "" or ISCSIADM == "":
+ if ISCSID == "" or ISCSIADM == "" or not has_libiscsi:
return False

log.info("ISCSID is %s" % (ISCSID,))
@@ -83,6 +87,7 @@ def iscsi_get_node_record(node_settings, record):

return None

+# FIXME replace with libiscsi use
def iscsi_make_node_autostart(disk):
sysfs_path = os.path.realpath("/sys/block/%s/device" %(disk,))
argv = [ "-m", "session", "-r", sysfs_path ]
@@ -95,119 +100,6 @@ def iscsi_make_node_autostart(disk):
iutil.execWithRedirect(ISCSIADM, argv,
stdout = "/dev/tty5", stderr="/dev/tty5")

-class iscsiTarget:
- def __init__(self, ipaddr, port=None, user=None, pw=None,
- user_in=None, pw_in=None):
- # FIXME: validate ipaddr
- self.ipaddr = ipaddr
- if not port: # FIXME: hack hack hack
- port = 3260
- self.port = str(port)
- self.user = user
- self.password = pw
- self.user_in = user_in
- self.password_in = pw_in
- self._portal = None
- self._nodes = []
-
- find_iscsi_files()
-
- def _getPortal(self):
- if self._portal is None:
- argv = [ "-m", "discovery", "-t", "st", "-p", self.ipaddr ]
- log.debug("iscsiadm %s" %(string.join(argv),))
- records = iutil.execWithCapture(ISCSIADM, argv, stderr="/dev/tty5")
- records = records.strip()
- for line in records.split("
"):
- log.debug(" %s" % (line,))
- if not line or line.find("found!") != -1:
- log.warn("no record found!")
- continue
- pnlist = line.split()
- if len(pnlist) != 2:
- log.warn("didn't get what we expected from iscsiadm")
- continue
- (portal, node) = pnlist
- if portal.startswith(self.ipaddr):
- self._portal = portal
- self._nodes.append(node)
- return self._portal
- portal = property(_getPortal)
-
- def _getNode(self):
- if len(self._nodes) == 0:
- # _getPortal() fills the list, if possible.
- self._getPortal()
- return self._nodes
- nodes = property(_getNode)
-
- def discover(self):
- argv = [ "-m", "discovery", "-t", "st", "-p",
- "%s:%s" % (self.ipaddr, self.port) ]
- log.debug("iscsiadm %s" %(string.join(argv),))
- rc = iutil.execWithRedirect(ISCSIADM, argv,
- stdout = "/dev/tty5", stderr="/dev/tty5")
- if rc != 0:
- log.warn("iscsiadm failed to discover on %s" %(self.ipaddr,))
- return False
- return True
-
- def addNode(self, node):
- if node is None or self.portal is None:
- log.warn("unable to find portal information")
- return
-
- argv = [ "-m", "node", "-T", node, "-p", self.portal,
- "-o", "new" ]
- log.debug("iscsiadm %s" %(string.join(argv),))
- iutil.execWithRedirect(ISCSIADM, argv,
- stdout = "/dev/tty5", stderr="/dev/tty5")
-
- def loginToNode(self, node):
- if node is None or self.portal is None:
- log.warn("unable to find portal information")
- return
-
- argv = [ "-m", "node", "-T", node, "-p", self.portal, "--login" ]
- log.debug("iscsiadm %s" %(string.join(argv),))
- rc = iutil.execWithRedirect(ISCSIADM, argv,
- stdout = "/dev/tty5", stderr="/dev/tty5")
- if rc != 0:
- log.warn("iscsiadm failed to login to %s" %(self.ipaddr,))
- return False
- return True
-
- def login(self):
- if len(self.nodes) == 0 or self.portal is None:
- log.warn("unable to find portal information")
- return False
-
-
- ret = False
- for node in self.nodes:
- if self.loginToNode(node):
- ret = True
- self.addNode(node)
-
- # Wait for udev to create the devices for the just added disks
- if ret:
- # It is possible when we get here the events for the new devices
- # are not send yet, so sleep to make sure the events are fired
- time.sleep(1)
- iutil.execWithRedirect("/sbin/udevadm", [ "settle" ],
- stdout = "/dev/tty5", stderr="/dev/tty5")
-
- # we return True if there were any successful logins for our portal.
- return ret
-
- def logout(self):
- for node in self.nodes:
- argv = [ "-m", "node", "-T", node, "-p", self.portal, "--logout" ]
- log.debug("iscsiadm %s" %(string.join(argv),))
- rc = iutil.execWithRedirect(ISCSIADM, argv,
- stdout = "/dev/tty5", stderr="/dev/tty5")
-
-
def randomIname():
"""Generate a random initiator name the same way as iscsi-iname"""

@@ -222,27 +114,38 @@ def randomIname():
s += dig[random.randrange(0, 32)]
return s

+def stabilize(intf = None):
+ # Wait for udev to create the devices for the just added disks
+ if intf:
+ w = intf.waitWindow(_("Scanning iSCSI nodes"),
+ _("Scanning iSCSI nodes"))
+ # It is possible when we get here the events for the new devices
+ # are not send yet, so sleep to make sure the events are fired
+ time.sleep(2)
+ iutil.execWithRedirect("/sbin/udevadm", [ "settle" ],
+ stdout = "/dev/tty5", stderr="/dev/tty5")
+ if intf:
+ w.pop()
+
class iscsi(object):
def __init__(self):
- self.fwinfo = self._queryFirmware()
- self.targets = []
+ self.nodes = []
self._initiator = ""
self.initiatorSet = False
- self.oldInitiatorFile = None
- self.iscsidStarted = False
+ self.started = False

- if self.fwinfo and self.fwinfo.has_key("iface.initiatorname"):
- self._initiator = self.fwinfo["iface.initiatorname"]
+ try:
+ initiatorname = libiscsi.get_firmware_initiator_name()
+ self._initiator = initiatorname
self.initiatorSet = True
+ except:
+ pass

def _getInitiator(self):
if self._initiator != "":
return self._initiator

- if self.fwinfo and self.fwinfo.has_key("iface.initiatorname"):
- return self.fwinfo["iface.initiatorname"]
- else:
- return randomIname()
+ return randomIname()

def _setInitiator(self, val):
if self._initiator != "" and val != self._initiator:
@@ -254,190 +157,37 @@ class iscsi(object):

initiator = property(_getInitiator, _setInitiator)

- def _queryFirmware(self):
- # Example:
- # [root@elm3b87 ~]# iscsiadm -m fw
- # iface.initiatorname = iqn.2007-05.com.ibm.beaverton.elm3b87:01
- # iface.hwaddress = 00:14:5e:b3:8e:b2
- # node.name = iqn.1992-08.com.netapp:sn.84183797
- # node.conn[0].address = 9.47.67.152
- # node.conn[0].port = 3260
-
- find_iscsi_files()
-
- if not has_iscsi():
- return
-
- retval = {}
-
- argv = [ "-m", "fw" ]
- log.debug("queryFirmware: ISCSIADM is %s" % (ISCSIADM,))
- result = iutil.execWithCapture(ISCSIADM, argv, stderr="/dev/tty5")
- result = result.strip()
-
- if len(result) == 0
- or result[0].find("iscsiadm -") != -1
- or result[0].find("iscsiadm: ") != -1:
- log.debug("queryFirmware: iscsiadm %s returns bad output: %s" %
- (argv,result))
-
- # Try querying the node records instead
- argv = [ "-m", "node", "-o", "show", "-S" ]
- result = iutil.execWithCapture(ISCSIADM, argv, stderr="/dev/tty5")
-
- if len(result) == 0
- or result[0].find("iscsiadm -") != -1
- or result[0].find("iscsiadm: ") != -1:
- log.debug("queryFirmware: iscsiadm %s returns bad output: %s" %
- (argv,result))
- return retval
-
- for line in result.split("
"):
- SPLIT = " = "
- idx = line.find(SPLIT)
- if idx != -1:
- lhs = line[:idx]
- rhs = line[idx+len(SPLIT):]
- retval[lhs] = rhs
-
- return retval
-
- def _startIscsiDaemon(self):
- psout = iutil.execWithCapture("/usr/bin/pidof", ["iscsid"])
- if psout.strip() == "":
- log.info("iSCSI startup")
- iutil.execWithRedirect(ISCSID, [],
- stdout="/dev/tty5", stderr="/dev/tty5")
- self.iscsidStarted = True
- time.sleep(2)
-
- def _stopIscsiDaemon(self):
- result = iutil.execWithCapture(ISCSIADM, ["-k", "0"], stderr="/dev/tty5")
- result.strip()
- if result == "":
- self.iscsidStarted = False
-
- def shutdown(self):
- if not has_iscsi():
+ def _startIBFT(self, intf = None):
+ if not flags.ibft:
return

- if flags.test:
- if self.oldInitiatorFile != None:
- f = open(INITIATOR_FILE, "w")
- for line in self.oldInitiatorFile:
- f.write(line)
- f.close ()
- self.oldInitiatorFile = None
- self._stopIscsiDaemon()
-
- def loginToDefaultDrive(self):
- # Example:
- # [root@elm3b87 ~]# iscsiadm -m discovery -t fw -l
- # Logging in to [iface: default, target:
iqn.1992-08.com.netapp:sn.84183797, portal: 9.47.67.152,3260]

-
- find_iscsi_files()
+ try:
+ found_nodes = libiscsi.discover_firmware()
+ except:
+ # an exception here means there is no ibft firmware, just return
+ return

- argv = [ "-m", "discovery", "-t", "fw", "-l" ]
- result = iutil.execWithCapture(ISCSIADM, argv, stderr="/dev/tty5")
- log.debug("iscsiadm result: %s" % (result,))
+ for node in found_nodes:
+ try:
+ node.login()
+ self.nodes.append(node)
+ except:
+ # FIXME, what to do when we cannot log in to a firmware
+ # provided node ??
+ pass

- start = result.find('[')
- end = result.rfind(']')
+ stabilize(intf)

- if start == -1 or end == -1:
- log.warn("could not find markers. iscsiadm returned: %s" %
- (result,))
+ def startup(self, intf = None):
+ if self.started:
return

- values = {}
- for kv in string.split(result[start+1:end], ', '):
- (k, v) = string.split(kv, ': ')
- values[k] = v
- del start, end
-
- if not values.has_key('target'):
- log.warn("iBFT data missing target. iscsiadm returned: %s" %
- (result,))
-
- if not values.has_key('portal'):
- log.warn("iBFT data missing portal. iscsiadm returned: %s" %
- (result,))
- else:
- portal = values['portal']
- comma = portal.find(',')
- if comma == -1:
- values['port'] = 3260
- else:
- values['port'] = portal[comma+1:]
- values['portal'] = portal[0:comma]
-
- if not values.has_key('chap-username') or not
- values.has_key('chap-password'):
- if values.has_key('chap-username'):
- log.warn("Invalid iBFT CHAP password. iscsiadm returned: %s" %
- (result,))
- return
- if values.has_key('chap-password'):
- log.warn("Invalid iBFT CHAP username. iscsiadm returned: %s" %
- (result,))
- return
-
- if not values.has_key('rev-chap-username') or not
- values.has_key('rev-chap-password'):
- if values.has_key('rev-chap-username'):
- log.warn("Invalid iBFT Reverse CHAP password. "
- "iscsiadm returned %s" % (result,))
- return
- if values.has_key('rev-chap-password'):
- log.warn("Invalid iBFT Reverse CHAP username. "
- "iscsiadm returned %s" % (result,))
- return
-
- target = values['target']
-
- renames = {
- 'portal': 'ipaddr',
- 'chap-username': 'user',
- 'chap-password': 'pw',
- 'rev-chap-username': 'user_in',
- 'rev-chap-password': 'pw_in',
- }
-
- for k,v in renames.items():
- if values.has_key(k):
- values[v] = values[k]
- del values[k]
-
- badKeys = filter(lambda x: not x in
- ('ipaddr','port','user','pw','user_in','pw_in'),
- values.keys())
- for k in badKeys:
- del values[k]
-
- # make a new target
- self.addTarget(**values)
-
-
- def startIBFT(self):
- # If there is a default drive in the iSCSI configuration, then
- # automatically attach to it. Do this before testing the initiator
- # name, because it is provided by the iBFT too
-
- if flags.ibft:
- self.loginToDefaultDrive()
-
- def startup(self, intf = None):
if not has_iscsi():
return

if not self.initiatorSet:
log.info("no initiator set")
return
- if flags.test:
- if os.access(INITIATOR_FILE, os.R_OK):
- f = open(INITIATOR_FILE, "r")
- self.oldInitiatorFile = f.readlines()
- f.close()

if intf:
w = intf.waitWindow(_("Initializing iSCSI initiator"),
@@ -453,120 +203,91 @@ class iscsi(object):
os.write(fd, "InitiatorName=%s
" %(self.initiator))
os.close(fd)

- if not os.path.isdir("/var/lib/iscsi"):
- os.makedirs("/var/lib/iscsi", 0660)
- for dir in ['nodes','send_targets','ifaces']:
+ for dir in ['ifaces','isns','nodes','send_targets','slp','stat ic']:
fulldir = "/var/lib/iscsi/%s" % (dir,)
if not os.path.isdir(fulldir):
- os.makedirs(fulldir, 0660)
+ os.makedirs(fulldir, 0755)

- self._startIscsiDaemon()
+ log.info("iSCSI startup")
+ iutil.execWithRedirect(ISCSID, [],
+ stdout="/dev/tty5", stderr="/dev/tty5")
+ time.sleep(1)

if intf:
w.pop()

+ self._startIBFT(intf)
+ self.started = True
+
def addTarget(self, ipaddr, port="3260", user=None, pw=None,
user_in=None, pw_in=None, intf=None):
- if not self.iscsidStarted:
- self.startup(intf)
- if not self.iscsidStarted:
- # can't start for some reason.... just fallback I guess
- return
-
- commentUser = '#'
- commentUser_in = '#'
-
- if user is not None or pw is not None:
- commentUser = '
- if user is None:
- raise ValueError, _("CHAP username is required if CHAP
password is defined.")

- if pw is None:
- raise ValueError, _("CHAP password is required if CHAP
username is defined.")

-
- if user_in is not None or pw_in is not None:
- commentUser_in = '
- if user_in is None:
- raise ValueError, _("Reverse CHAP username is required if
reverse CHAP password is defined.")

- if pw_in is None:
- raise ValueError, _("Reverse CHAP password is required if
reverse CHAP username is defined.")

-
- # If either a user/pw pair was specified or a user_in/pw_in was
- # specified, then CHAP is specified.
- if commentUser == ' or commentUser_in == ':
- commentChap = '
- else:
- commentChap = '#'
-
-
- oldIscsidFile = []
- try:
- f = open(ISCSID_CONF, "r")
- oldIscsidFile = f.readlines()
- f.close()
- except IOError, x:
- if x.errno != errno.ENOENT:
- raise RuntimeError, "Cannot open %s for read." % (ISCSID_CONF,)
+ authinfo = None
+ found = 0
+ logged_in = 0

- try:
- f = open(ISCSID_CONF, "w")
- except:
- raise RuntimeError, "Cannot open %s for write." % (ISCSID_CONF,)
-
- vals = {
- "node.session.auth.authmethod = ": [commentChap, "CHAP"],
- "node.session.auth.username = ": [commentUser, user],
- "node.session.auth.password = ": [commentUser, pw],
- "node.session.auth.username_in = ": [commentUser_in, user_in],
- "node.session.auth.password_in = ": [commentUser_in, pw_in],
- "discovery.sendtargets.auth.authmethod = ": [commentChap, "CHAP"],
- "discovery.sendtargets.auth.username = ": [commentUser, user],
- "discovery.sendtargets.auth.password = ": [commentUser, pw],
- "discovery.sendtargets.auth.username_in = ":
- [commentUser_in, user_in],
- "discovery.sendtargets.auth.password_in = ":
- [commentUser_in, pw_in],
- }
-
- for line in oldIscsidFile:
- s = line.strip()
- # grab the cr/lf/cr+lf
- nl = line[line.find(s)+len(s):]
- found = False
- for (k, (c, v)) in vals.items():
- if line.find(k) != -1:
- f.write("%s%s%s%s" % (c, k, v, nl))
- found=True
- del vals[k]
- break
- if not found:
- f.write(line)
-
- for (k, (c, v)) in vals.items():
- f.write("%s%s%s
" % (c, k, v))
- f.close ()
-
- t = iscsiTarget(ipaddr, port, user, pw, user_in, pw_in)
- if not t.discover():
- return
- if not t.login():
- return
- self.targets.append(t)
- return
+ if not has_iscsi():
+ raise IOError, _("iSCSI not available")
+ if not self.initiatorSet:
+ raise ValueError, _("No initiator name set")
+
+ self.startup(intf)
+
+ if user:
+ # Note may raise a ValueError
+ authinfo = libiscsi.chapAuthInfo(username=user, password=pw,
+ reverse_username=user_in,
+ reverse_password=pw_in)
+ # Note may raise an IOError
+ found_nodes = libiscsi.discover_sendtargets(address=ipaddr,
+ port=int(port),
+ authinfo=authinfo)
+ if found_nodes == None:
+ raise IOError, _("No iSCSI nodes discovered")
+
+ if intf:
+ w = intf.waitWindow(_("Logging in to iSCSI nodes"),
+ _("Logging in to iSCSI nodes"))
+
+ for node in found_nodes:
+ # skip nodes we already have
+ if node in self.nodes:
+ continue
+
+ found = found + 1
+ try:
+ if (authinfo):
+ node.setAuth(authinfo)
+ node.login()
+ self.nodes.append(node)
+ logged_in = logged_in + 1
+ except:
+ # some nodes may require different credentials
+ pass
+
+ if intf:
+ w.pop()
+
+ if found == 0:
+ raise IOError, _("No new iSCSI nodes discovered")
+
+ if logged_in == 0:
+ raise IOError, _("Could not log in to any of the discovered nodes")
+
+ stabilize(intf)

def writeKS(self, f):
if not self.initiatorSet:
return
f.write("iscsiname %s
" %(self.initiator,))
- for t in self.targets:
- f.write("iscsi --ipaddr %s --port %s" %(t.ipaddr, t.port))
- if t.user:
- f.write(" --user %s" %(t.user,))
- if t.password:
- f.write(" --password %s" %(t.password,))
- if t.user_in:
- f.write(" --reverse-user %s" % (t.user_in,))
- if t.password_in:
- f.write(" --reverse-password %s" % (t.password_in,))
+ for n in self.nodes:
+ f.write("iscsi --ipaddr %s --port %s" %(n.address, n.port))
+ auth = n.getAuth()
+ if auth:
+ f.write(" --user %s" %(n.username,))
+ f.write(" --password %s" %(n.password,))
+ if len(auth.reverse_username):
+ f.write(" --reverse-user %s" % (n.reverse_username,))
+ f.write(" --reverse-password %s" % (n.reverse_password,))
f.write("
")

def write(self, instPath, anaconda):
@@ -601,10 +322,10 @@ class iscsi(object):
os.close(fd)

# copy "db" files. *sigh*
- if not os.path.isdir(instPath + "/var/lib/iscsi"):
- os.makedirs(instPath + "/var/lib/iscsi", 0755)
- for d in ("/var/lib/iscsi/nodes", "/var/lib/iscsi/send_targets"):
- if os.path.isdir(d):
- shutil.copytree(d, instPath + d)
+ if os.path.isdir(instPath + "/var/lib/iscsi"):
+ shutil.rmtree(instPath + "/var/lib/iscsi")
+ if os.path.isdir("/var/lib/iscsi"):
+ shutil.copytree("/var/lib/iscsi", instPath + "/var/lib/iscsi",
+ symlinks=True)

# vim:tw=78:ts=4:et:sw=4
diff --git a/iw/autopart_type.py b/iw/autopart_type.py
index f166eab..3b36682 100644
--- a/iw/autopart_type.py
+++ b/iw/autopart_type.py
@@ -247,7 +247,6 @@ class PartitionTypeWindow(InstallWindow):
rc = dialog.run()
if rc == gtk.RESPONSE_CANCEL:
break
- return rc

initiator = dxml.get_widget("iscsiInitiatorEntry").get_text()
initiator.strip()
@@ -297,6 +296,9 @@ class PartitionTypeWindow(InstallWindow):
except ValueError, e:
self.intf.messageWindow(_("Error"), str(e))
continue
+ except IOError, e:
+ self.intf.messageWindow(_("Error"), str(e))
+ rc = gtk.RESPONSE_CANCEL
break

dialog.destroy()
@@ -362,12 +364,15 @@ class PartitionTypeWindow(InstallWindow):
dialog.destroy()

if rc != gtk.RESPONSE_CANCEL:
+ w = self.intf.waitWindow(_("Rescanning disks"),
+ _("Rescanning disks"))
partitions.partitionObjectsInitialize(self.anacond a)
createAllowedDrivesStore(self.diskset.disks,
self.partitions.autoClearPartDrives,
self.drivelist,
disallowDrives=[self.anaconda.updateSrc])
self._fillBootStore()
+ w.pop()

def _fillBootStore(self):
bootstore = self.bootcombo.get_model()
diff --git a/kickstart.py b/kickstart.py
index eafd4d8..9305ef0 100644
--- a/kickstart.py
+++ b/kickstart.py
@@ -313,9 +313,6 @@ class IscsiName(commands.iscsiname.FC6_IscsiName):
retval = commands.iscsiname.FC6_IscsiName.parse(self, args)

self.handler.id.iscsi.initiator = self.iscsiname
- self.handler.id.iscsi.startIBFT()
- # FIXME: flush the drive dict so we figure drives out again
- isys.flushDriveDict()
return retval

class Keyboard(commands.keyboard.FC3_Keyboard):
diff --git a/partitions.py b/partitions.py
index 74a9e11..a22c54b 100644
--- a/partitions.py
+++ b/partitions.py
@@ -62,6 +62,9 @@ def partitionObjectsInitialize(anaconda):
if anaconda.dir == DISPATCH_BACK:
return

+ # make ibft configured iscsi disks available when findrootparts was skipped
+ anaconda.id.iscsi.startup(anaconda.intf)
+
# ensure zfcp devs are up
anaconda.id.zfcp.startup()

diff --git a/rescue.py b/rescue.py
index 2ae35e6..42e5b96 100644
--- a/rescue.py
+++ b/rescue.py
@@ -205,6 +205,7 @@ def runRescue(anaconda, instClass):
else:
break

+ anaconda.intf = None
screen.finish()

# Early shell access with no disk access attempts
diff --git a/scripts/upd-instroot b/scripts/upd-instroot
index ae37ab6..6271dc9 100755
--- a/scripts/upd-instroot
+++ b/scripts/upd-instroot
@@ -439,6 +439,7 @@ usr/$LIBDIR/python?.?/site-packages/firstboot
usr/$LIBDIR/python?.?/site-packages/gtk*
usr/$LIBDIR/python?.?/site-packages/gtk*/gtk
usr/$LIBDIR/python?.?/site-packages/ixf86configmodule.so
+usr/$LIBDIR/python?.?/site-packages/libiscsimodule.so
usr/$LIBDIR/python?.?/site-packages/libusermodule.so
usr/$LIBDIR/python?.?/site-packages/partedmodule.so
usr/$LIBDIR/python?.?/site-packages/rhpl
@@ -446,6 +447,7 @@ usr/$LIBDIR/python?.?/site-packages/rpmmodule.so
usr/$LIBDIR/python?.?/site-packages/xf86config.py
usr/$LIBDIR/python?.?/xml/etree/
usr/$LIBDIR/rpm/rpmpopt
+usr/$LIBDIR/libiscsi.so*
usr/$LIBDIR/libsqlite3.so*
usr/$LIBDIR/xorg/modules
usr/$LIBDIR/xserver/SecurityPolicy
diff --git a/textw/partition_text.py b/textw/partition_text.py
index 1944ee1..c8381d1 100644
--- a/textw/partition_text.py
+++ b/textw/partition_text.py
@@ -1650,7 +1650,7 @@ class PartitionTypeWindow:
else:
try:
return self.addIscsiDriveDialog(screen)
- except ValueError, e:
+ except (ValueError, IOError), e:
ButtonChoiceWindow(screen, _("Error"), str(e))
return INSTALL_BACK

diff --git a/upgrade.py b/upgrade.py
index d8d1e75..1c4685d 100644
--- a/upgrade.py
+++ b/upgrade.py
@@ -149,6 +149,9 @@ def findRootParts(anaconda):
anaconda.dispatch.skipStep("installtype", skip = 0)

def findExistingRoots(anaconda, upgradeany = 0):
+ # make ibft configured iscsi disks available
+ anaconda.id.iscsi.startup(anaconda.intf)
+
if not flags.setupFilesystems:
relstr = partedUtils.getReleaseString (anaconda.rootPath)
if ((flags.cmdline.has_key("upgradeany")) or
--
1.6.1.2

_______________________________________________
Anaconda-devel-list mailing list
Anaconda-devel-list@redhat.com
https://www.redhat.com/mailman/listinfo/anaconda-devel-list
 
Old 02-04-2009, 08:56 AM
Martin Sivak
 
Default Rewrite iscsi code using libiscsi

Quite long reading, but the logic looks OK.

I have one suggestion, which would solve our recent python libiscsi discussion.

The libiscsi.chapAuthInfo object doesn't have to have the C part to store the information (Python can store strings too..), it could be quite ordinary object (maybe derived from dict as is common in python world) and the part which stores the values to C structure for use in the Node object could be in the Node object itself. Then we won't be passing any problematic C structures around and it would behave as expected in every situation I described during the pyiscsi review.

Martin

----- "Hans de Goede" <hdegoede@redhat.com> wrote:

> Hi All,
>
> This patch replaces the iscsi.py code with new code using libiscsi,
> getting
> rid of the awefull configfile mangling to set auth info hack, and in
> general
> making it much cleaner.
>
> Fixes:
> -Report error when we cannot add a disk instead of silently failing
> (461830)
> -Report error when trying to use iscsi from kickstart without having
> an
> iscsiname directive first (463156)
> -Better feedback while scanning iscsi disks
> -Make ibft work with chap and 2-way chap
> -Make ibft configured disks available for upgrades and in rescue mode
> -Make ibft boot work even when iscsi-initiator-utils is installed
> after the
> kernel in the transaction
>
> Note:
> libiscsi is available in Fedora now
> ---
> backend.py | 11 +
> iscsi.py | 521
> +++++++++++------------------------------------
> iw/autopart_type.py | 7 +-
> kickstart.py | 3 -
> partitions.py | 3 +
> rescue.py | 1 +
> scripts/upd-instroot | 2 +
> textw/partition_text.py | 2 +-
> upgrade.py | 3 +
> 9 files changed, 148 insertions(+), 405 deletions(-)
>
> diff --git a/backend.py b/backend.py
> index 3008671..06f6c2b 100644
> --- a/backend.py
> +++ b/backend.py
> @@ -79,9 +79,20 @@ class AnacondaBackend:
> log.error("Could not copy firmware file %s: %s" %
> (f,
> e.strerror))
>
> def doPostInstall(self, anaconda):
> + has_iscsi_disk = False
> +
> + # See if we have an iscsi disk. If we do we rerun mkinitrd,
> as
> + # the initrd might need iscsi-initiator-utils, and chances
> are
> + # it was not installed yet the first time mkinitrd was run,
> as
> + # mkinitrd does not require it.
> + for disk in anaconda.id.diskset.disks.keys():
> + if isys.driveIsIscsi(disk):
> + has_iscsi_disk = True
> +
> if anaconda.id.extraModules:
> self.copyFirmware(anaconda)
>
> + if anaconda.id.extraModules or has_iscsi_disk:
> for (n, arch, tag) in
> self.kernelVersionList(anaconda.rootPath):
> packages.recreateInitrd(n, anaconda.rootPath)
>
> diff --git a/iscsi.py b/iscsi.py
> index a4d301e..24f7090 100644
> --- a/iscsi.py
> +++ b/iscsi.py
> @@ -36,6 +36,11 @@ log = logging.getLogger("anaconda")
> import gettext
> _ = lambda x: gettext.ldgettext("anaconda", x)
>
> +has_libiscsi = True
> +try:
> + import libiscsi
> +except:
> + has_libiscsi = False
>
> # Note that stage2 copies all files under /sbin to /usr/sbin
> global ISCSID
> @@ -43,7 +48,6 @@ ISCSID=""
> global ISCSIADM
> ISCSIADM = ""
> INITIATOR_FILE="/etc/iscsi/initiatorname.iscsi"
> -ISCSID_CONF="/etc/iscsi/iscsid.conf"
>
> def find_iscsi_files():
> global ISCSID
> @@ -61,7 +65,7 @@ def find_iscsi_files():
>
> def has_iscsi():
> find_iscsi_files()
> - if ISCSID == "" or ISCSIADM == "":
> + if ISCSID == "" or ISCSIADM == "" or not has_libiscsi:
> return False
>
> log.info("ISCSID is %s" % (ISCSID,))
> @@ -83,6 +87,7 @@ def iscsi_get_node_record(node_settings, record):
>
> return None
>
> +# FIXME replace with libiscsi use
> def iscsi_make_node_autostart(disk):
> sysfs_path = os.path.realpath("/sys/block/%s/device" %(disk,))
> argv = [ "-m", "session", "-r", sysfs_path ]
> @@ -95,119 +100,6 @@ def iscsi_make_node_autostart(disk):
> iutil.execWithRedirect(ISCSIADM, argv,
> stdout = "/dev/tty5",
> stderr="/dev/tty5")
>
> -class iscsiTarget:
> - def __init__(self, ipaddr, port=None, user=None, pw=None,
> - user_in=None, pw_in=None):
> - # FIXME: validate ipaddr
> - self.ipaddr = ipaddr
> - if not port: # FIXME: hack hack hack
> - port = 3260
> - self.port = str(port)
> - self.user = user
> - self.password = pw
> - self.user_in = user_in
> - self.password_in = pw_in
> - self._portal = None
> - self._nodes = []
> -
> - find_iscsi_files()
> -
> - def _getPortal(self):
> - if self._portal is None:
> - argv = [ "-m", "discovery", "-t", "st", "-p", self.ipaddr
> ]
> - log.debug("iscsiadm %s" %(string.join(argv),))
> - records = iutil.execWithCapture(ISCSIADM, argv,
> stderr="/dev/tty5")
> - records = records.strip()
> - for line in records.split("
"):
> - log.debug(" %s" % (line,))
> - if not line or line.find("found!") != -1:
> - log.warn("no record found!")
> - continue
> - pnlist = line.split()
> - if len(pnlist) != 2:
> - log.warn("didn't get what we expected from
> iscsiadm")
> - continue
> - (portal, node) = pnlist
> - if portal.startswith(self.ipaddr):
> - self._portal = portal
> - self._nodes.append(node)
> - return self._portal
> - portal = property(_getPortal)
> -
> - def _getNode(self):
> - if len(self._nodes) == 0:
> - # _getPortal() fills the list, if possible.
> - self._getPortal()
> - return self._nodes
> - nodes = property(_getNode)
> -
> - def discover(self):
> - argv = [ "-m", "discovery", "-t", "st", "-p",
> - "%s:%s" % (self.ipaddr, self.port) ]
> - log.debug("iscsiadm %s" %(string.join(argv),))
> - rc = iutil.execWithRedirect(ISCSIADM, argv,
> - stdout = "/dev/tty5",
> stderr="/dev/tty5")
> - if rc != 0:
> - log.warn("iscsiadm failed to discover on %s"
> %(self.ipaddr,))
> - return False
> - return True
> -
> - def addNode(self, node):
> - if node is None or self.portal is None:
> - log.warn("unable to find portal information")
> - return
> -
> - argv = [ "-m", "node", "-T", node, "-p", self.portal,
> - "-o", "new" ]
> - log.debug("iscsiadm %s" %(string.join(argv),))
> - iutil.execWithRedirect(ISCSIADM, argv,
> - stdout = "/dev/tty5",
> stderr="/dev/tty5")
> -
> - def loginToNode(self, node):
> - if node is None or self.portal is None:
> - log.warn("unable to find portal information")
> - return
> -
> - argv = [ "-m", "node", "-T", node, "-p", self.portal,
> "--login" ]
> - log.debug("iscsiadm %s" %(string.join(argv),))
> - rc = iutil.execWithRedirect(ISCSIADM, argv,
> - stdout = "/dev/tty5",
> stderr="/dev/tty5")
> - if rc != 0:
> - log.warn("iscsiadm failed to login to %s"
> %(self.ipaddr,))
> - return False
> - return True
> -
> - def login(self):
> - if len(self.nodes) == 0 or self.portal is None:
> - log.warn("unable to find portal information")
> - return False
> -
> -
> - ret = False
> - for node in self.nodes:
> - if self.loginToNode(node):
> - ret = True
> - self.addNode(node)
> -
> - # Wait for udev to create the devices for the just added
> disks
> - if ret:
> - # It is possible when we get here the events for the new
> devices
> - # are not send yet, so sleep to make sure the events are
> fired
> - time.sleep(1)
> - iutil.execWithRedirect("/sbin/udevadm", [ "settle" ],
> - stdout = "/dev/tty5",
> stderr="/dev/tty5")
> -
> - # we return True if there were any successful logins for our
> portal.
> - return ret
> -
> - def logout(self):
> - for node in self.nodes:
> - argv = [ "-m", "node", "-T", node, "-p", self.portal,
> "--logout" ]
> - log.debug("iscsiadm %s" %(string.join(argv),))
> - rc = iutil.execWithRedirect(ISCSIADM, argv,
> - stdout = "/dev/tty5",
> stderr="/dev/tty5")
> -
> -
> def randomIname():
> """Generate a random initiator name the same way as
> iscsi-iname"""
>
> @@ -222,27 +114,38 @@ def randomIname():
> s += dig[random.randrange(0, 32)]
> return s
>
> +def stabilize(intf = None):
> + # Wait for udev to create the devices for the just added disks
> + if intf:
> + w = intf.waitWindow(_("Scanning iSCSI nodes"),
> + _("Scanning iSCSI nodes"))
> + # It is possible when we get here the events for the new devices
> + # are not send yet, so sleep to make sure the events are fired
> + time.sleep(2)
> + iutil.execWithRedirect("/sbin/udevadm", [ "settle" ],
> + stdout = "/dev/tty5", stderr="/dev/tty5")
> + if intf:
> + w.pop()
> +
> class iscsi(object):
> def __init__(self):
> - self.fwinfo = self._queryFirmware()
> - self.targets = []
> + self.nodes = []
> self._initiator = ""
> self.initiatorSet = False
> - self.oldInitiatorFile = None
> - self.iscsidStarted = False
> + self.started = False
>
> - if self.fwinfo and
> self.fwinfo.has_key("iface.initiatorname"):
> - self._initiator = self.fwinfo["iface.initiatorname"]
> + try:
> + initiatorname = libiscsi.get_firmware_initiator_name()
> + self._initiator = initiatorname
> self.initiatorSet = True
> + except:
> + pass
>
> def _getInitiator(self):
> if self._initiator != "":
> return self._initiator
>
> - if self.fwinfo and
> self.fwinfo.has_key("iface.initiatorname"):
> - return self.fwinfo["iface.initiatorname"]
> - else:
> - return randomIname()
> + return randomIname()
>
> def _setInitiator(self, val):
> if self._initiator != "" and val != self._initiator:
> @@ -254,190 +157,37 @@ class iscsi(object):
>
> initiator = property(_getInitiator, _setInitiator)
>
> - def _queryFirmware(self):
> - # Example:
> - # [root@elm3b87 ~]# iscsiadm -m fw
> - # iface.initiatorname =
> iqn.2007-05.com.ibm.beaverton.elm3b87:01
> - # iface.hwaddress = 00:14:5e:b3:8e:b2
> - # node.name = iqn.1992-08.com.netapp:sn.84183797
> - # node.conn[0].address = 9.47.67.152
> - # node.conn[0].port = 3260
> -
> - find_iscsi_files()
> -
> - if not has_iscsi():
> - return
> -
> - retval = {}
> -
> - argv = [ "-m", "fw" ]
> - log.debug("queryFirmware: ISCSIADM is %s" % (ISCSIADM,))
> - result = iutil.execWithCapture(ISCSIADM, argv,
> stderr="/dev/tty5")
> - result = result.strip()
> -
> - if len(result) == 0
> - or result[0].find("iscsiadm -") != -1
> - or result[0].find("iscsiadm: ") != -1:
> - log.debug("queryFirmware: iscsiadm %s returns bad output:
> %s" %
> - (argv,result))
> -
> - # Try querying the node records instead
> - argv = [ "-m", "node", "-o", "show", "-S" ]
> - result = iutil.execWithCapture(ISCSIADM, argv,
> stderr="/dev/tty5")
> -
> - if len(result) == 0
> - or result[0].find("iscsiadm -") != -1
> - or result[0].find("iscsiadm: ") != -1:
> - log.debug("queryFirmware: iscsiadm %s returns bad
> output: %s" %
> - (argv,result))
> - return retval
> -
> - for line in result.split("
"):
> - SPLIT = " = "
> - idx = line.find(SPLIT)
> - if idx != -1:
> - lhs = line[:idx]
> - rhs = line[idx+len(SPLIT):]
> - retval[lhs] = rhs
> -
> - return retval
> -
> - def _startIscsiDaemon(self):
> - psout = iutil.execWithCapture("/usr/bin/pidof", ["iscsid"])
> - if psout.strip() == "":
> - log.info("iSCSI startup")
> - iutil.execWithRedirect(ISCSID, [],
> - stdout="/dev/tty5",
> stderr="/dev/tty5")
> - self.iscsidStarted = True
> - time.sleep(2)
> -
> - def _stopIscsiDaemon(self):
> - result = iutil.execWithCapture(ISCSIADM, ["-k", "0"],
> stderr="/dev/tty5")
> - result.strip()
> - if result == "":
> - self.iscsidStarted = False
> -
> - def shutdown(self):
> - if not has_iscsi():
> + def _startIBFT(self, intf = None):
> + if not flags.ibft:
> return
>
> - if flags.test:
> - if self.oldInitiatorFile != None:
> - f = open(INITIATOR_FILE, "w")
> - for line in self.oldInitiatorFile:
> - f.write(line)
> - f.close ()
> - self.oldInitiatorFile = None
> - self._stopIscsiDaemon()
> -
> - def loginToDefaultDrive(self):
> - # Example:
> - # [root@elm3b87 ~]# iscsiadm -m discovery -t fw -l
> - # Logging in to [iface: default, target:
> iqn.1992-08.com.netapp:sn.84183797, portal: 9.47.67.152,3260]
> -
> - find_iscsi_files()
> + try:
> + found_nodes = libiscsi.discover_firmware()
> + except:
> + # an exception here means there is no ibft firmware,
> just return
> + return
>
> - argv = [ "-m", "discovery", "-t", "fw", "-l" ]
> - result = iutil.execWithCapture(ISCSIADM, argv,
> stderr="/dev/tty5")
> - log.debug("iscsiadm result: %s" % (result,))
> + for node in found_nodes:
> + try:
> + node.login()
> + self.nodes.append(node)
> + except:
> + # FIXME, what to do when we cannot log in to a
> firmware
> + # provided node ??
> + pass
>
> - start = result.find('[')
> - end = result.rfind(']')
> + stabilize(intf)
>
> - if start == -1 or end == -1:
> - log.warn("could not find markers. iscsiadm returned: %s"
> %
> - (result,))
> + def startup(self, intf = None):
> + if self.started:
> return
>
> - values = {}
> - for kv in string.split(result[start+1:end], ', '):
> - (k, v) = string.split(kv, ': ')
> - values[k] = v
> - del start, end
> -
> - if not values.has_key('target'):
> - log.warn("iBFT data missing target. iscsiadm returned:
> %s" %
> - (result,))
> -
> - if not values.has_key('portal'):
> - log.warn("iBFT data missing portal. iscsiadm returned:
> %s" %
> - (result,))
> - else:
> - portal = values['portal']
> - comma = portal.find(',')
> - if comma == -1:
> - values['port'] = 3260
> - else:
> - values['port'] = portal[comma+1:]
> - values['portal'] = portal[0:comma]
> -
> - if not values.has_key('chap-username') or not
> - values.has_key('chap-password'):
> - if values.has_key('chap-username'):
> - log.warn("Invalid iBFT CHAP password. iscsiadm
> returned: %s" %
> - (result,))
> - return
> - if values.has_key('chap-password'):
> - log.warn("Invalid iBFT CHAP username. iscsiadm
> returned: %s" %
> - (result,))
> - return
> -
> - if not values.has_key('rev-chap-username') or not
> - values.has_key('rev-chap-password'):
> - if values.has_key('rev-chap-username'):
> - log.warn("Invalid iBFT Reverse CHAP password. "
> - "iscsiadm returned %s" % (result,))
> - return
> - if values.has_key('rev-chap-password'):
> - log.warn("Invalid iBFT Reverse CHAP username. "
> - "iscsiadm returned %s" % (result,))
> - return
> -
> - target = values['target']
> -
> - renames = {
> - 'portal': 'ipaddr',
> - 'chap-username': 'user',
> - 'chap-password': 'pw',
> - 'rev-chap-username': 'user_in',
> - 'rev-chap-password': 'pw_in',
> - }
> -
> - for k,v in renames.items():
> - if values.has_key(k):
> - values[v] = values[k]
> - del values[k]
> -
> - badKeys = filter(lambda x: not x in
> -
> ('ipaddr','port','user','pw','user_in','pw_in'),
> - values.keys())
> - for k in badKeys:
> - del values[k]
> -
> - # make a new target
> - self.addTarget(**values)
> -
> -
> - def startIBFT(self):
> - # If there is a default drive in the iSCSI configuration,
> then
> - # automatically attach to it. Do this before testing the
> initiator
> - # name, because it is provided by the iBFT too
> -
> - if flags.ibft:
> - self.loginToDefaultDrive()
> -
> - def startup(self, intf = None):
> if not has_iscsi():
> return
>
> if not self.initiatorSet:
> log.info("no initiator set")
> return
> - if flags.test:
> - if os.access(INITIATOR_FILE, os.R_OK):
> - f = open(INITIATOR_FILE, "r")
> - self.oldInitiatorFile = f.readlines()
> - f.close()
>
> if intf:
> w = intf.waitWindow(_("Initializing iSCSI initiator"),
> @@ -453,120 +203,91 @@ class iscsi(object):
> os.write(fd, "InitiatorName=%s
" %(self.initiator))
> os.close(fd)
>
> - if not os.path.isdir("/var/lib/iscsi"):
> - os.makedirs("/var/lib/iscsi", 0660)
> - for dir in ['nodes','send_targets','ifaces']:
> + for dir in
> ['ifaces','isns','nodes','send_targets','slp','stat ic']:
> fulldir = "/var/lib/iscsi/%s" % (dir,)
> if not os.path.isdir(fulldir):
> - os.makedirs(fulldir, 0660)
> + os.makedirs(fulldir, 0755)
>
> - self._startIscsiDaemon()
> + log.info("iSCSI startup")
> + iutil.execWithRedirect(ISCSID, [],
> + stdout="/dev/tty5",
> stderr="/dev/tty5")
> + time.sleep(1)
>
> if intf:
> w.pop()
>
> + self._startIBFT(intf)
> + self.started = True
> +
> def addTarget(self, ipaddr, port="3260", user=None, pw=None,
> user_in=None, pw_in=None, intf=None):
> - if not self.iscsidStarted:
> - self.startup(intf)
> - if not self.iscsidStarted:
> - # can't start for some reason.... just fallback I
> guess
> - return
> -
> - commentUser = '#'
> - commentUser_in = '#'
> -
> - if user is not None or pw is not None:
> - commentUser = '
> - if user is None:
> - raise ValueError, _("CHAP username is required if
> CHAP
> password is defined.")
> - if pw is None:
> - raise ValueError, _("CHAP password is required if
> CHAP
> username is defined.")
> -
> - if user_in is not None or pw_in is not None:
> - commentUser_in = '
> - if user_in is None:
> - raise ValueError, _("Reverse CHAP username is
> required if
> reverse CHAP password is defined.")
> - if pw_in is None:
> - raise ValueError, _("Reverse CHAP password is
> required if
> reverse CHAP username is defined.")
> -
> - # If either a user/pw pair was specified or a user_in/pw_in
> was
> - # specified, then CHAP is specified.
> - if commentUser == ' or commentUser_in == ':
> - commentChap = '
> - else:
> - commentChap = '#'
> -
> -
> - oldIscsidFile = []
> - try:
> - f = open(ISCSID_CONF, "r")
> - oldIscsidFile = f.readlines()
> - f.close()
> - except IOError, x:
> - if x.errno != errno.ENOENT:
> - raise RuntimeError, "Cannot open %s for read." %
> (ISCSID_CONF,)
> + authinfo = None
> + found = 0
> + logged_in = 0
>
> - try:
> - f = open(ISCSID_CONF, "w")
> - except:
> - raise RuntimeError, "Cannot open %s for write." %
> (ISCSID_CONF,)
> -
> - vals = {
> - "node.session.auth.authmethod = ": [commentChap,
> "CHAP"],
> - "node.session.auth.username = ": [commentUser, user],
> - "node.session.auth.password = ": [commentUser, pw],
> - "node.session.auth.username_in = ": [commentUser_in,
> user_in],
> - "node.session.auth.password_in = ": [commentUser_in,
> pw_in],
> - "discovery.sendtargets.auth.authmethod = ": [commentChap,
> "CHAP"],
> - "discovery.sendtargets.auth.username = ": [commentUser,
> user],
> - "discovery.sendtargets.auth.password = ": [commentUser,
> pw],
> - "discovery.sendtargets.auth.username_in = ":
> - [commentUser_in, user_in],
> - "discovery.sendtargets.auth.password_in = ":
> - [commentUser_in, pw_in],
> - }
> -
> - for line in oldIscsidFile:
> - s = line.strip()
> - # grab the cr/lf/cr+lf
> - nl = line[line.find(s)+len(s):]
> - found = False
> - for (k, (c, v)) in vals.items():
> - if line.find(k) != -1:
> - f.write("%s%s%s%s" % (c, k, v, nl))
> - found=True
> - del vals[k]
> - break
> - if not found:
> - f.write(line)
> -
> - for (k, (c, v)) in vals.items():
> - f.write("%s%s%s
" % (c, k, v))
> - f.close ()
> -
> - t = iscsiTarget(ipaddr, port, user, pw, user_in, pw_in)
> - if not t.discover():
> - return
> - if not t.login():
> - return
> - self.targets.append(t)
> - return
> + if not has_iscsi():
> + raise IOError, _("iSCSI not available")
> + if not self.initiatorSet:
> + raise ValueError, _("No initiator name set")
> +
> + self.startup(intf)
> +
> + if user:
> + # Note may raise a ValueError
> + authinfo = libiscsi.chapAuthInfo(username=user,
> password=pw,
> +
> reverse_username=user_in,
> + reverse_password=pw_in)
> + # Note may raise an IOError
> + found_nodes = libiscsi.discover_sendtargets(address=ipaddr,
> + port=int(port),
> +
> authinfo=authinfo)
> + if found_nodes == None:
> + raise IOError, _("No iSCSI nodes discovered")
> +
> + if intf:
> + w = intf.waitWindow(_("Logging in to iSCSI nodes"),
> + _("Logging in to iSCSI nodes"))
> +
> + for node in found_nodes:
> + # skip nodes we already have
> + if node in self.nodes:
> + continue
> +
> + found = found + 1
> + try:
> + if (authinfo):
> + node.setAuth(authinfo)
> + node.login()
> + self.nodes.append(node)
> + logged_in = logged_in + 1
> + except:
> + # some nodes may require different credentials
> + pass
> +
> + if intf:
> + w.pop()
> +
> + if found == 0:
> + raise IOError, _("No new iSCSI nodes discovered")
> +
> + if logged_in == 0:
> + raise IOError, _("Could not log in to any of the
> discovered nodes")
> +
> + stabilize(intf)
>
> def writeKS(self, f):
> if not self.initiatorSet:
> return
> f.write("iscsiname %s
" %(self.initiator,))
> - for t in self.targets:
> - f.write("iscsi --ipaddr %s --port %s" %(t.ipaddr,
> t.port))
> - if t.user:
> - f.write(" --user %s" %(t.user,))
> - if t.password:
> - f.write(" --password %s" %(t.password,))
> - if t.user_in:
> - f.write(" --reverse-user %s" % (t.user_in,))
> - if t.password_in:
> - f.write(" --reverse-password %s" % (t.password_in,))
> + for n in self.nodes:
> + f.write("iscsi --ipaddr %s --port %s" %(n.address,
> n.port))
> + auth = n.getAuth()
> + if auth:
> + f.write(" --user %s" %(n.username,))
> + f.write(" --password %s" %(n.password,))
> + if len(auth.reverse_username):
> + f.write(" --reverse-user %s" %
> (n.reverse_username,))
> + f.write(" --reverse-password %s" %
> (n.reverse_password,))
> f.write("
")
>
> def write(self, instPath, anaconda):
> @@ -601,10 +322,10 @@ class iscsi(object):
> os.close(fd)
>
> # copy "db" files. *sigh*
> - if not os.path.isdir(instPath + "/var/lib/iscsi"):
> - os.makedirs(instPath + "/var/lib/iscsi", 0755)
> - for d in ("/var/lib/iscsi/nodes",
> "/var/lib/iscsi/send_targets"):
> - if os.path.isdir(d):
> - shutil.copytree(d, instPath + d)
> + if os.path.isdir(instPath + "/var/lib/iscsi"):
> + shutil.rmtree(instPath + "/var/lib/iscsi")
> + if os.path.isdir("/var/lib/iscsi"):
> + shutil.copytree("/var/lib/iscsi", instPath +
> "/var/lib/iscsi",
> + symlinks=True)
>
> # vim:tw=78:ts=4:et:sw=4
> diff --git a/iw/autopart_type.py b/iw/autopart_type.py
> index f166eab..3b36682 100644
> --- a/iw/autopart_type.py
> +++ b/iw/autopart_type.py
> @@ -247,7 +247,6 @@ class PartitionTypeWindow(InstallWindow):
> rc = dialog.run()
> if rc == gtk.RESPONSE_CANCEL:
> break
> - return rc
>
> initiator =
> dxml.get_widget("iscsiInitiatorEntry").get_text()
> initiator.strip()
> @@ -297,6 +296,9 @@ class PartitionTypeWindow(InstallWindow):
> except ValueError, e:
> self.intf.messageWindow(_("Error"), str(e))
> continue
> + except IOError, e:
> + self.intf.messageWindow(_("Error"), str(e))
> + rc = gtk.RESPONSE_CANCEL
> break
>
> dialog.destroy()
> @@ -362,12 +364,15 @@ class PartitionTypeWindow(InstallWindow):
> dialog.destroy()
>
> if rc != gtk.RESPONSE_CANCEL:
> + w = self.intf.waitWindow(_("Rescanning disks"),
> + _("Rescanning disks"))
> partitions.partitionObjectsInitialize(self.anacond a)
> createAllowedDrivesStore(self.diskset.disks,
>
> self.partitions.autoClearPartDrives,
> self.drivelist,
>
> disallowDrives=[self.anaconda.updateSrc])
> self._fillBootStore()
> + w.pop()
>
> def _fillBootStore(self):
> bootstore = self.bootcombo.get_model()
> diff --git a/kickstart.py b/kickstart.py
> index eafd4d8..9305ef0 100644
> --- a/kickstart.py
> +++ b/kickstart.py
> @@ -313,9 +313,6 @@ class
> IscsiName(commands.iscsiname.FC6_IscsiName):
> retval = commands.iscsiname.FC6_IscsiName.parse(self, args)
>
> self.handler.id.iscsi.initiator = self.iscsiname
> - self.handler.id.iscsi.startIBFT()
> - # FIXME: flush the drive dict so we figure drives out again
> - isys.flushDriveDict()
> return retval
>
> class Keyboard(commands.keyboard.FC3_Keyboard):
> diff --git a/partitions.py b/partitions.py
> index 74a9e11..a22c54b 100644
> --- a/partitions.py
> +++ b/partitions.py
> @@ -62,6 +62,9 @@ def partitionObjectsInitialize(anaconda):
> if anaconda.dir == DISPATCH_BACK:
> return
>
> + # make ibft configured iscsi disks available when findrootparts
> was skipped
> + anaconda.id.iscsi.startup(anaconda.intf)
> +
> # ensure zfcp devs are up
> anaconda.id.zfcp.startup()
>
> diff --git a/rescue.py b/rescue.py
> index 2ae35e6..42e5b96 100644
> --- a/rescue.py
> +++ b/rescue.py
> @@ -205,6 +205,7 @@ def runRescue(anaconda, instClass):
> else:
> break
>
> + anaconda.intf = None
> screen.finish()
>
> # Early shell access with no disk access attempts
> diff --git a/scripts/upd-instroot b/scripts/upd-instroot
> index ae37ab6..6271dc9 100755
> --- a/scripts/upd-instroot
> +++ b/scripts/upd-instroot
> @@ -439,6 +439,7 @@ usr/$LIBDIR/python?.?/site-packages/firstboot
> usr/$LIBDIR/python?.?/site-packages/gtk*
> usr/$LIBDIR/python?.?/site-packages/gtk*/gtk
> usr/$LIBDIR/python?.?/site-packages/ixf86configmodule.so
> +usr/$LIBDIR/python?.?/site-packages/libiscsimodule.so
> usr/$LIBDIR/python?.?/site-packages/libusermodule.so
> usr/$LIBDIR/python?.?/site-packages/partedmodule.so
> usr/$LIBDIR/python?.?/site-packages/rhpl
> @@ -446,6 +447,7 @@ usr/$LIBDIR/python?.?/site-packages/rpmmodule.so
> usr/$LIBDIR/python?.?/site-packages/xf86config.py
> usr/$LIBDIR/python?.?/xml/etree/
> usr/$LIBDIR/rpm/rpmpopt
> +usr/$LIBDIR/libiscsi.so*
> usr/$LIBDIR/libsqlite3.so*
> usr/$LIBDIR/xorg/modules
> usr/$LIBDIR/xserver/SecurityPolicy
> diff --git a/textw/partition_text.py b/textw/partition_text.py
> index 1944ee1..c8381d1 100644
> --- a/textw/partition_text.py
> +++ b/textw/partition_text.py
> @@ -1650,7 +1650,7 @@ class PartitionTypeWindow:
> else:
> try:
> return self.addIscsiDriveDialog(screen)
> - except ValueError, e:
> + except (ValueError, IOError), e:
> ButtonChoiceWindow(screen, _("Error"), str(e))
> return INSTALL_BACK
>
> diff --git a/upgrade.py b/upgrade.py
> index d8d1e75..1c4685d 100644
> --- a/upgrade.py
> +++ b/upgrade.py
> @@ -149,6 +149,9 @@ def findRootParts(anaconda):
> anaconda.dispatch.skipStep("installtype", skip = 0)
>
> def findExistingRoots(anaconda, upgradeany = 0):
> + # make ibft configured iscsi disks available
> + anaconda.id.iscsi.startup(anaconda.intf)
> +
> if not flags.setupFilesystems:
> relstr = partedUtils.getReleaseString (anaconda.rootPath)
> if ((flags.cmdline.has_key("upgradeany")) or
> --
> 1.6.1.2
>
> _______________________________________________
> Anaconda-devel-list mailing list
> Anaconda-devel-list@redhat.com
> https://www.redhat.com/mailman/listinfo/anaconda-devel-list

_______________________________________________
Anaconda-devel-list mailing list
Anaconda-devel-list@redhat.com
https://www.redhat.com/mailman/listinfo/anaconda-devel-list
 
Old 02-05-2009, 08:09 PM
Chris Lumens
 
Default Rewrite iscsi code using libiscsi

Okay, I'll be the picky one.

> diff --git a/backend.py b/backend.py
> index 3008671..06f6c2b 100644
> --- a/backend.py
> +++ b/backend.py
> @@ -79,9 +79,20 @@ class AnacondaBackend:
> log.error("Could not copy firmware file %s: %s" % (f,
> e.strerror))
>
> def doPostInstall(self, anaconda):
> + has_iscsi_disk = False
> +
> + # See if we have an iscsi disk. If we do we rerun mkinitrd, as
> + # the initrd might need iscsi-initiator-utils, and chances are
> + # it was not installed yet the first time mkinitrd was run, as
> + # mkinitrd does not require it.
> + for disk in anaconda.id.diskset.disks.keys():
> + if isys.driveIsIscsi(disk):
> + has_iscsi_disk = True

Don't you want to break here after setting has_iscsi_disk=True, since
there's no need to keep scanning?

> @@ -222,27 +114,38 @@ def randomIname():
> s += dig[random.randrange(0, 32)]
> return s
>
> +def stabilize(intf = None):
> + # Wait for udev to create the devices for the just added disks
> + if intf:
> + w = intf.waitWindow(_("Scanning iSCSI nodes"),
> + _("Scanning iSCSI nodes"))
> + # It is possible when we get here the events for the new devices
> + # are not send yet, so sleep to make sure the events are fired
> + time.sleep(2)
> + iutil.execWithRedirect("/sbin/udevadm", [ "settle" ],
> + stdout = "/dev/tty5", stderr="/dev/tty5")

In general, we don't want to specify the path to a program when we use
execWith*. Instead, you just want to call "udevadm" and pass
searchPath=1.

> diff --git a/kickstart.py b/kickstart.py
> index eafd4d8..9305ef0 100644
> --- a/kickstart.py
> +++ b/kickstart.py
> @@ -313,9 +313,6 @@ class IscsiName(commands.iscsiname.FC6_IscsiName):
> retval = commands.iscsiname.FC6_IscsiName.parse(self, args)
>
> self.handler.id.iscsi.initiator = self.iscsiname
> - self.handler.id.iscsi.startIBFT()
> - # FIXME: flush the drive dict so we figure drives out again
> - isys.flushDriveDict()
> return retval
>
> class Keyboard(commands.keyboard.FC3_Keyboard):

Are any kickstart syntax changes needed for this new iscsi stuff?

> diff --git a/rescue.py b/rescue.py
> index 2ae35e6..42e5b96 100644
> --- a/rescue.py
> +++ b/rescue.py
> @@ -205,6 +205,7 @@ def runRescue(anaconda, instClass):
> else:
> break
>
> + anaconda.intf = None
> screen.finish()
>
> # Early shell access with no disk access attempts

I'm not sure what the point of this one is. Could you explain?

I'm having a little trouble following the meat of this patch, which is
probably just due to the fact that sometimes diff makes a colossal mess
of things. Could you either post the full iscsi.py somewhere or break
it into smaller chunks? Thanks.

- Chris

_______________________________________________
Anaconda-devel-list mailing list
Anaconda-devel-list@redhat.com
https://www.redhat.com/mailman/listinfo/anaconda-devel-list
 
Old 02-06-2009, 08:48 AM
Hans de Goede
 
Default Rewrite iscsi code using libiscsi

Chris Lumens wrote:

Okay, I'll be the picky one.


diff --git a/backend.py b/backend.py
index 3008671..06f6c2b 100644
--- a/backend.py
+++ b/backend.py
@@ -79,9 +79,20 @@ class AnacondaBackend:
log.error("Could not copy firmware file %s: %s" % (f,
e.strerror))


def doPostInstall(self, anaconda):
+ has_iscsi_disk = False
+
+ # See if we have an iscsi disk. If we do we rerun mkinitrd, as
+ # the initrd might need iscsi-initiator-utils, and chances are
+ # it was not installed yet the first time mkinitrd was run, as
+ # mkinitrd does not require it.
+ for disk in anaconda.id.diskset.disks.keys():
+ if isys.driveIsIscsi(disk):
+ has_iscsi_disk = True


Don't you want to break here after setting has_iscsi_disk=True, since
there's no need to keep scanning?



Fixed.


@@ -222,27 +114,38 @@ def randomIname():
s += dig[random.randrange(0, 32)]
return s

+def stabilize(intf = None):
+ # Wait for udev to create the devices for the just added disks
+ if intf:
+ w = intf.waitWindow(_("Scanning iSCSI nodes"),
+ _("Scanning iSCSI nodes"))
+ # It is possible when we get here the events for the new devices
+ # are not send yet, so sleep to make sure the events are fired
+ time.sleep(2)
+ iutil.execWithRedirect("/sbin/udevadm", [ "settle" ],
+ stdout = "/dev/tty5", stderr="/dev/tty5")


In general, we don't want to specify the path to a program when we use
execWith*. Instead, you just want to call "udevadm" and pass
searchPath=1.



Fixed.


diff --git a/kickstart.py b/kickstart.py
index eafd4d8..9305ef0 100644
--- a/kickstart.py
+++ b/kickstart.py
@@ -313,9 +313,6 @@ class IscsiName(commands.iscsiname.FC6_IscsiName):
retval = commands.iscsiname.FC6_IscsiName.parse(self, args)

self.handler.id.iscsi.initiator = self.iscsiname
- self.handler.id.iscsi.startIBFT()
- # FIXME: flush the drive dict so we figure drives out again
- isys.flushDriveDict()
return retval

class Keyboard(commands.keyboard.FC3_Keyboard):


Are any kickstart syntax changes needed for this new iscsi stuff?



No


diff --git a/rescue.py b/rescue.py
index 2ae35e6..42e5b96 100644
--- a/rescue.py
+++ b/rescue.py
@@ -205,6 +205,7 @@ def runRescue(anaconda, instClass):
else:
break

+ anaconda.intf = None
screen.finish()

# Early shell access with no disk access attempts


I'm not sure what the point of this one is. Could you explain?



We create an Rescue interface in top of screen, and then destroy screen (by
calling screen.finish(), so the Rescue interface we have can no longer be used,
notice if we need an interface again below, we recreate it.


Since the new iscsi code can use anaconda.intf in the rescue path (while making
ibft disks available in the rescue environment), it is important that
anaconda.intf does not reference to the Rescueinterface using the no longer
valid screen object.



I'm having a little trouble following the meat of this patch, which is
probably just due to the fact that sometimes diff makes a colossal mess
of things. Could you either post the full iscsi.py somewhere or break
it into smaller chunks? Thanks.


Sure, here it is:
http://fpaste.org/paste/2983

This includes the execWithRedirect fix you asked for.

Regards,

Hans

_______________________________________________
Anaconda-devel-list mailing list
Anaconda-devel-list@redhat.com
https://www.redhat.com/mailman/listinfo/anaconda-devel-list
 

Thread Tools




All times are GMT. The time now is 06:40 PM.

VBulletin, Copyright ©2000 - 2014, Jelsoft Enterprises Ltd.
Content Relevant URLs by vBSEO ©2007, Crawlability, Inc.
Copyright 2007 - 2008, www.linux-archive.org