Various iSCSI fixes [PATCH 4/4]: anaconda-iscsi-rhel5-to-master2.patch

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi All,

Forward port the following rhel5 iscsi changes to master:
c0beca8cfd3af9a38dee89fc2ffb83bb5b2b6e55 Do not try to initialize iSCSI drive, e9556f9e39629534b4b44ba64c7fef6b981b4f0e Add full CHAP support to iSCSI. (rhbz# 2979c1195d9031b16d61ff14e3a6b0dcb3ee548f Don't set iscsi devices to autostart ( 4960fffcddce97ffdd6d80f9b18f757c25d37ff5 Support iSCSI CHAP and Reverse CHAP au
5a44a5a6bc90fdf056db1e9e2d4191703387c15f Add ibft flag to ease in testing.
0c566de27f4beb311baef2c49761924ced188da2 Make iBFT reading explicit from a high
84c6d1f92ab2508158104b1c97f17b673b717bea Fix typo.

This brings master fully inline with the rhel-5 branch iscsi support except for this commit:
031032e230cd651aab96e9ed6fc105f1611a074a
Add support for reading NIC setup from the iBFT table (#445721)
Use ksdevice=ibft ip=ibft for now, I'll set it as default right after wider testing

Which makes many changes to the loader network code which was significantly changed (by using network manager) in master. Someone who knows the code better (and has equipment to actually test this) will need to forward port this to master.

Regards,

Hans


p.s.

I've tested that iscsi still works after all these changes, but I haven't tested any of the new features (ibft, authentication) I'll test authentication after plumbers, for testing ibft I lack the equipment.

Forward port the following rhel5 iscsi changes to master:
c0beca8cfd3af9a38dee89fc2ffb83bb5b2b6e55 Do not try to initialize iSCSI drive, when the portal cannot be detected (#435173)
e9556f9e39629534b4b44ba64c7fef6b981b4f0e Add full CHAP support to iSCSI. (rhbz#432819)
2979c1195d9031b16d61ff14e3a6b0dcb3ee548f Don't set iscsi devices to autostart (rhbz#437891)
4960fffcddce97ffdd6d80f9b18f757c25d37ff5 Support iSCSI CHAP and Reverse CHAP authentication (rhbz#402431, rhbz#432819)
5a44a5a6bc90fdf056db1e9e2d4191703387c15f Add ibft flag to ease in testing.
0c566de27f4beb311baef2c49761924ced188da2 Make iBFT reading explicit from a higher level, so the target list doesn't get obliterated in the anaconda.id.reset() path.
84c6d1f92ab2508158104b1c97f17b673b717bea Fix typo.

This brings master fully inline with the rhel-5 branch iscsi support except\
for this commit:
031032e230cd651aab96e9ed6fc105f1611a074a 
Add support for reading NIC setup from the iBFT table (#445721)
Use ksdevice=ibft ip=ibft for now, I'll set it as default right after wider testing

Which makes many changes to the loader network code which was significantly
changed (by using network manager) in master. Someone who knows the code better
(and has equipment to actually test this) will need to forward port this to
master.

diff --git a/anaconda b/anaconda
index 6ed54a5..7bdef43 100755
--- a/anaconda
+++ b/anaconda
@@ -264,6 +264,8 @@ def parseOptions():
     op.add_option("--nodmraid", dest="dmraid", action="store_false", default=True)
     op.add_option("--dmraid", action="store_true")
 
+    op.add_option("--noibft", dest="ibft", action="store_false", default=True)
+    op.add_option("--ibft", action="store_true")
     op.add_option("--noiscsi", dest="iscsi", action="store_false", default=False)
     op.add_option("--iscsi", action="store_true")
 
@@ -699,6 +701,9 @@ if __name__ == "__main__":
                 if len(cargs[1]) > 0:
                     vncS.vncconnectport = cargs[1]
 
+    if opts.ibft:
+        flags.ibft = 1
+
     if opts.iscsi:
         flags.iscsi = 1
 
diff --git a/anaconda.spec b/anaconda.spec
index 5c950ac..d7bec12 100644
--- a/anaconda.spec
+++ b/anaconda.spec
@@ -45,6 +45,7 @@ BuildRequires: elfutils-devel
 BuildRequires: gettext >= %{gettextver}
 BuildRequires: gtk2-devel
 BuildRequires: intltool >= %{intltoolver}
+BuildRequires: iscsi-initiator-utils >= 6.2.0.868-0.9
 BuildRequires: isomd5sum-devel
 BuildRequires: libX11-devel
 BuildRequires: libXt-devel
diff --git a/flags.py b/flags.py
index 85d0771..2d77bd7 100644
--- a/flags.py
+++ b/flags.py
@@ -64,6 +64,7 @@ class Flags:
 	self.__dict__['flags']['test'] = 0
 	self.__dict__['flags']['rootpath'] = 0
 	self.__dict__['flags']['livecdInstall'] = 0
+	self.__dict__['flags']['ibft'] = 1
 	self.__dict__['flags']['iscsi'] = 0
 	self.__dict__['flags']['serial'] = 0
 	self.__dict__['flags']['setupFilesystems'] = 1
diff --git a/iscsi.py b/iscsi.py
index a00a43d..ed96884 100644
--- a/iscsi.py
+++ b/iscsi.py
@@ -20,6 +20,7 @@
 
 from constants import *
 import os
+import errno
 import string
 import signal
 import iutil
@@ -40,6 +41,7 @@ ISCSID=""
 global ISCSIADM
 ISCSIADM = ""
 INITIATOR_FILE="/etc/iscsi/initiatorname.iscsi"
+ISCSID_CONF="/etc/iscsi/iscsid.conf"
 
 def find_iscsi_files():
     global ISCSID
@@ -69,7 +71,8 @@ def has_iscsi():
     return True
 
 class iscsiTarget:
-    def __init__(self, ipaddr, port = None, user = None, pw = None):
+    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
@@ -77,6 +80,8 @@ class iscsiTarget:
         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 = []
 
@@ -122,10 +127,13 @@ class iscsiTarget:
             return False
         return True
 
-    def startNode(self, node):
+    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", "update", "-n", "node.conn[0].startup",
-                 "-v", "automatic" ]
+                 "-o", "new" ]
         log.debug("iscsiadm %s" %(string.join(argv),))
         iutil.execWithRedirect(ISCSIADM, argv,
                                stdout = "/dev/tty5", stderr="/dev/tty5")
@@ -150,7 +158,7 @@ class iscsiTarget:
         for node in self.nodes:
             if self.loginToNode(node):
                 ret = True
-                self.startNode(node)
+                self.addNode(node)
 
         # we return True if there were any successful logins for our portal.
         return ret
@@ -191,6 +199,13 @@ class iscsi(object):
             self.initiatorSet = True
             self.startup()
 
+            # 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 _getInitiator(self):
         if self._initiator != "":
             return self._initiator
@@ -230,6 +245,24 @@ class iscsi(object):
         log.debug("queryFirmware: ISCSIADM is %s" % (ISCSIADM,))
         result = iutil.execWithCapture(ISCSIADM, argv)
         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)
+
+            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("\n"):
             SPLIT = " = "
             idx = line.find(SPLIT)
@@ -284,33 +317,90 @@ class iscsi(object):
 
     def loginToDefaultDrive(self):
         # Example:
-        # [root@elm3b87 ~]# iscsiadm -m fw -l
+        # [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()
 
-        argv = [ "-m", "fw", "-l" ]
+        argv = [ "-m", "discovery", "-t", "fw", "-l" ]
         result = iutil.execWithCapture(ISCSIADM, argv)
+        log.debug("iscsiadm result: %s" % (result,))
 
-        TARGET = "target: "
-        PORTAL = ", portal: "
-        END = "]"
-        idxTarget = result.find(TARGET)
-        idxPortal = result.find(PORTAL)
-        idxEnd = result.find(END)
+        start = result.find('[')
+        end = result.rfind(']')
 
-        if idxTarget == -1 or idxPortal == -1 or idxEnd == -1:
-            return None
+        if start == -1 or end == -1:
+            log.warn("could not find markers.  iscsiadm returned: %s" %
+                (result,))
+            return
 
-        target = result[idxTarget + len(TARGET) : idxPortal]
-        portal = result[idxPortal + len(PORTAL) : idxEnd]
-        port = 3260
-        idxPort = portal.find(',')
-        if idxPort != -1:
-            port = portal[idxPort + 1 :]
-            portal = portal[:idxPort]
+        values = {}
+        for kv in string.split(result[start+1:end], ', '):
+            (k, v) = string.split(kv, ': ')
+            values[k] = v
+        del start, end
 
-        return (target, portal, port)
+        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 startup(self, intf = None):
         if not has_iscsi():
@@ -348,21 +438,6 @@ class iscsi(object):
 
         self._startIscsiDaemon()
 
-        # 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
-
-        # this will actually log us in, but it won't create the iscsi db
-        # entries.
-        default = self.loginToDefaultDrive()
-        if not default is None:
-            (node, ipaddr, port) = default
-            t = iscsiTarget(ipaddr, port, None, None)
-            # this actually creates the entries.
-            t.discover()
-            # and this sets them to auto-start
-            t.startNode(node)
-
         for t in self.targets:
             if not t.discover():
                 continue
@@ -371,15 +446,87 @@ class iscsi(object):
         if intf:
             w.pop()
 
-    def addTarget(self, ipaddr, port = "3260", user = None, pw = None,
-                  intf = None):
+    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
 
-        t = iscsiTarget(ipaddr, port, user, pw)
+        commentUser = '#'
+        commentUser_in = '#'
+
+        if user is not None or pw is not None:
+            commentUser = ''
+            if user is None:
+                raise ValueError, "user is required"
+            if pw is None:
+                raise ValueError, "pw is required"
+
+        if user_in is not None or pw_in is not None:
+            commentUser_in = ''
+            if user_in is None:
+                raise ValueError, "user_in is required"
+            if pw_in is None:
+                raise ValueError, "pw_in is required"
+
+        # 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,)
+
+        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\n" % (c, k, v))
+        f.close ()
+
+        t = iscsiTarget(ipaddr, port, user, pw, user_in, pw_in)
         if not t.discover():
             return
         if not t.login():
@@ -397,6 +544,10 @@ class iscsi(object):
                 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,))
             f.write("\n")
 
     def write(self, instPath):
diff --git a/iw/autopart_type.py b/iw/autopart_type.py
index b31dbdb..c4e90e2 100644
--- a/iw/autopart_type.py
+++ b/iw/autopart_type.py
@@ -236,11 +236,8 @@ class PartitionTypeWindow(InstallWindow):
         dialog.show_all()
         sg = gtk.SizeGroup(gtk.SIZE_GROUP_HORIZONTAL)
         map(lambda x: sg.add_widget(dxml.get_widget(x)),
-            ("iscsiAddrEntry", "iscsiInitiatorEntry"))
-
-        # we don't currently support username or password...
-        map(lambda x: dxml.get_widget(x).hide(),
-            ("userLabel", "passLabel", "userEntry", "passEntry"))
+            ("iscsiAddrEntry", "iscsiInitiatorEntry", "userEntry", "passEntry",
+             "userinEntry", "passinEntry"))
 
         # get the initiator name if it exists and don't allow changing
         # once set
@@ -261,11 +258,44 @@ class PartitionTypeWindow(InstallWindow):
                 self.intf.messageWindow(_("Invalid Initiator Name"),
                                         _("You must provide an initiator name."))
                 continue
+
             self.anaconda.id.iscsi.initiator = initiator
 
             target = dxml.get_widget("iscsiAddrEntry").get_text().strip()
             user = dxml.get_widget("userEntry").get_text().strip()
             pw = dxml.get_widget("passEntry").get_text().strip()
+            user_in = dxml.get_widget("userinEntry").get_text().strip()
+            pw_in = dxml.get_widget("passinEntry").get_text().strip()
+
+            if len(user) == 0:
+                user = None
+            if len(pw) == 0:
+                pw = None
+            if len(user_in) == 0:
+                user_in = None
+            if len(pw_in) == 0:
+                pw_in = None
+
+            if user is not None or pw is not None:
+                if user is None:
+                    self.intf.messageWindow(_("Missing value"),
+                        _("CHAP username is required if CHAP password is defined."))
+                    continue
+                if pw is None:
+                    self.intf.messageWindow(_("Missing value"),
+                        _("CHAP password is required if CHAP username is defined."))
+                    continue
+
+            if user_in is not None or pw_in is not None:
+                if user_in is None:
+                    self.intf.messageWindow(_("Missing value"),
+                        _("Reverse CHAP username is required if reverse CHAP password is defined."))
+                    continue
+                if pw_in is None:
+                    self.intf.messageWindow(_("Missing value"),
+                        _("Reverse CHAP password is required if reverse CHAP username is defined."))
+                    continue
+
             err = None
             try:
                 idx = target.rfind(":")
@@ -281,10 +311,11 @@ class PartitionTypeWindow(InstallWindow):
             except network.IPError, msg:
                 err = msg
             if err:
-                self.intf.messageWindow(_("Error with Data"), "%s" %(msg,))
+                self.intf.messageWindow(_("Error with Data"), "%s" %(err,))
                 continue
 
-            self.anaconda.id.iscsi.addTarget(ip, port, user, pw, self.intf)
+            self.anaconda.id.iscsi.addTarget(ip, port, user, pw, user_in, pw_in,
+                                             self.intf)
             break
 
         dialog.destroy()
diff --git a/textw/partition_text.py b/textw/partition_text.py
index b09213f..1f87d14 100644
--- a/textw/partition_text.py
+++ b/textw/partition_text.py
@@ -1687,10 +1687,43 @@ class PartitionTypeWindow:
                                         _("Configure iSCSI Parameters"),
                                         _("To use iSCSI disks, you must provide the address of your iSCSI target and the iSCSI initiator name you've configured for your host."),
                                         prompts = [ _("Target IP Address"),
-                                                    _("iSCSI Initiator Name") ])
+                                                    _("iSCSI Initiator Name"),
+                                                    _("CHAP username"),
+                                                    _("CHAP password"),
+                                                    _("Reverse CHAP username"),
+                                                    _("Reverse CHAP password") ])
         if button == TEXT_CANCEL_CHECK:
             return INSTALL_BACK
 
+        (user, pw, user_in, pw_in) = entries[2:5]
+
+        if len(user) == 0:
+            user = None
+        if len(pw) == 0:
+            pw = None
+        if len(user_in) == 0:
+            user_in = None
+        if len(pw_in) == 0:
+            pw_in = None
+
+        if user is not None or pw is not None:
+            if user is None:
+                ButtonChoiceWindow(screen, _("Missing value"),
+                    _("Username is required when password is present."))
+            if pw is None:
+                ButtonChoiceWindow(screen, _("Missing value"),
+                    _("Password is required when username is present."))
+
+        if user_in is not None or pw_in is not None:
+            if user_in is None:
+                ButtonChoiceWindow(screen, _("Missing value"),
+                                   _("Reverse username is required when"
+                                     "reverse password is present."))
+            if pw_in is None:
+                ButtonChoiceWindow(screen, _("Missing value"),
+                                   _("Reverse password is required when"
+                                     "reverse username is present."))
+
         target = entries[0].strip()
         try:
             idx = target.rfind(":")
@@ -1709,6 +1742,6 @@ class PartitionTypeWindow:
         iname = entries[1].strip()
         if not self.anaconda.id.iscsi.initiatorSet:
             self.anaconda.id.iscsi.initiator = iname
-        self.anaconda.id.iscsi.addTarget(ip, port)
+        self.anaconda.id.iscsi.addTarget(ip, port, user, pw, user_in, pw_in)
                                         
         return INSTALL_OK
diff --git a/ui/iscsi-config.glade b/ui/iscsi-config.glade
index 6b6fa8c..f1c80f8 100644
--- a/ui/iscsi-config.glade
+++ b/ui/iscsi-config.glade
@@ -162,7 +162,7 @@
 	    <widget class="GtkTable" id="iscsiTable">
 	      <property name="border_width">12</property>
 	      <property name="visible">True</property>
-	      <property name="n_rows">4</property>
+	      <property name="n_rows">6</property>
 	      <property name="n_columns">2</property>
 	      <property name="homogeneous">False</property>
 	      <property name="row_spacing">6</property>
@@ -215,7 +215,7 @@
 		  <property name="right_attach">2</property>
 		  <property name="top_attach">0</property>
 		  <property name="bottom_attach">1</property>
-		  <property name="x_options"></property>
+		  <property name="x_options">fill</property>
 		  <property name="y_options"></property>
 		</packing>
 	      </child>
@@ -258,16 +258,16 @@
 		  <property name="max_length">0</property>
 		  <property name="text" translatable="yes"></property>
 		  <property name="has_frame">True</property>
-		  <property name="invisible_char">*</property>
+		  <property name="invisible_char">�</property>
 		  <property name="activates_default">False</property>
-		  <property name="width_chars">32</property>
+		  <property name="width_chars">45</property>
 		</widget>
 		<packing>
 		  <property name="left_attach">1</property>
 		  <property name="right_attach">2</property>
 		  <property name="top_attach">1</property>
 		  <property name="bottom_attach">2</property>
-		  <property name="x_options"></property>
+		  <property name="x_options">fill</property>
 		  <property name="y_options"></property>
 		</packing>
 	      </child>
@@ -275,7 +275,7 @@
 	      <child>
 		<widget class="GtkLabel" id="userLabel">
 		  <property name="visible">True</property>
-		  <property name="label" translatable="yes">&lt;b&gt;_Username:&lt;/b&gt;</property>
+		  <property name="label" translatable="yes">&lt;b&gt;CHAP _Username:&lt;/b&gt;</property>
 		  <property name="use_underline">True</property>
 		  <property name="use_markup">True</property>
 		  <property name="justify">GTK_JUSTIFY_LEFT</property>
@@ -302,9 +302,32 @@
 	      </child>
 
 	      <child>
+		<widget class="GtkEntry" id="userEntry">
+		  <property name="visible">True</property>
+		  <property name="can_focus">True</property>
+		  <property name="editable">True</property>
+		  <property name="visibility">True</property>
+		  <property name="max_length">0</property>
+		  <property name="text" translatable="yes"></property>
+		  <property name="has_frame">True</property>
+		  <property name="invisible_char">�</property>
+		  <property name="activates_default">False</property>
+		  <property name="width_chars">45</property>
+		</widget>
+		<packing>
+		  <property name="left_attach">1</property>
+		  <property name="right_attach">2</property>
+		  <property name="top_attach">2</property>
+		  <property name="bottom_attach">3</property>
+		  <property name="x_options">fill</property>
+		  <property name="y_options"></property>
+		</packing>
+	      </child>
+
+	      <child>
 		<widget class="GtkLabel" id="passLabel">
 		  <property name="visible">True</property>
-		  <property name="label" translatable="yes">&lt;b&gt;_Password:&lt;/b&gt;</property>
+		  <property name="label" translatable="yes">&lt;b&gt;CHAP _Password:&lt;/b&gt;</property>
 		  <property name="use_underline">True</property>
 		  <property name="use_markup">True</property>
 		  <property name="justify">GTK_JUSTIFY_LEFT</property>
@@ -331,7 +354,59 @@
 	      </child>
 
 	      <child>
-		<widget class="GtkEntry" id="userEntry">
+		<widget class="GtkEntry" id="passEntry">
+		  <property name="visible">True</property>
+		  <property name="can_focus">True</property>
+		  <property name="editable">True</property>
+		  <property name="visibility">False</property>
+		  <property name="max_length">0</property>
+		  <property name="text" translatable="yes"></property>
+		  <property name="has_frame">True</property>
+		  <property name="invisible_char">�</property>
+		  <property name="activates_default">False</property>
+		  <property name="width_chars">45</property>
+		</widget>
+		<packing>
+		  <property name="left_attach">1</property>
+		  <property name="right_attach">2</property>
+		  <property name="top_attach">3</property>
+		  <property name="bottom_attach">4</property>
+		  <property name="x_options">fill</property>
+		  <property name="y_options"></property>
+		</packing>
+	      </child>
+
+	      <child>
+		<widget class="GtkLabel" id="userinLabel">
+		  <property name="visible">True</property>
+		  <property name="label" translatable="yes">&lt;b&gt;Reverse CHAP U_sername:&lt;/b&gt;</property>
+		  <property name="use_underline">True</property>
+		  <property name="use_markup">True</property>
+		  <property name="justify">GTK_JUSTIFY_LEFT</property>
+		  <property name="wrap">False</property>
+		  <property name="selectable">False</property>
+		  <property name="xalign">0</property>
+		  <property name="yalign">0.5</property>
+		  <property name="xpad">0</property>
+		  <property name="ypad">0</property>
+		  <property name="mnemonic_widget">userinEntry</property>
+		  <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+		  <property name="width_chars">-1</property>
+		  <property name="single_line_mode">False</property>
+		  <property name="angle">0</property>
+		</widget>
+		<packing>
+		  <property name="left_attach">0</property>
+		  <property name="right_attach">1</property>
+		  <property name="top_attach">4</property>
+		  <property name="bottom_attach">5</property>
+		  <property name="x_options">fill</property>
+		  <property name="y_options"></property>
+		</packing>
+	      </child>
+
+	      <child>
+		<widget class="GtkEntry" id="userinEntry">
 		  <property name="visible">True</property>
 		  <property name="can_focus">True</property>
 		  <property name="editable">True</property>
@@ -341,18 +416,49 @@
 		  <property name="has_frame">True</property>
 		  <property name="invisible_char">â?¢</property>
 		  <property name="activates_default">False</property>
+		  <property name="width_chars">45</property>
 		</widget>
 		<packing>
 		  <property name="left_attach">1</property>
 		  <property name="right_attach">2</property>
-		  <property name="top_attach">2</property>
-		  <property name="bottom_attach">3</property>
+		  <property name="top_attach">4</property>
+		  <property name="bottom_attach">5</property>
+		  <property name="x_options">fill</property>
 		  <property name="y_options"></property>
 		</packing>
 	      </child>
 
 	      <child>
-		<widget class="GtkEntry" id="passEntry">
+		<widget class="GtkLabel" id="passinLabel">
+		  <property name="visible">True</property>
+		  <property name="label" translatable="yes">&lt;b&gt;Reverse CHAP P_assword:&lt;/b&gt;</property>
+		  <property name="use_underline">True</property>
+		  <property name="use_markup">True</property>
+		  <property name="justify">GTK_JUSTIFY_LEFT</property>
+		  <property name="wrap">False</property>
+		  <property name="selectable">False</property>
+		  <property name="xalign">0</property>
+		  <property name="yalign">0.5</property>
+		  <property name="xpad">0</property>
+		  <property name="ypad">0</property>
+		  <property name="mnemonic_widget">passinEntry</property>
+		  <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+		  <property name="width_chars">-1</property>
+		  <property name="single_line_mode">False</property>
+		  <property name="angle">0</property>
+		</widget>
+		<packing>
+		  <property name="left_attach">0</property>
+		  <property name="right_attach">1</property>
+		  <property name="top_attach">5</property>
+		  <property name="bottom_attach">6</property>
+		  <property name="x_options">fill</property>
+		  <property name="y_options"></property>
+		</packing>
+	      </child>
+
+	      <child>
+		<widget class="GtkEntry" id="passinEntry">
 		  <property name="visible">True</property>
 		  <property name="can_focus">True</property>
 		  <property name="editable">True</property>
@@ -362,15 +468,18 @@
 		  <property name="has_frame">True</property>
 		  <property name="invisible_char">â?¢</property>
 		  <property name="activates_default">False</property>
+		  <property name="width_chars">45</property>
 		</widget>
 		<packing>
 		  <property name="left_attach">1</property>
 		  <property name="right_attach">2</property>
-		  <property name="top_attach">3</property>
-		  <property name="bottom_attach">4</property>
+		  <property name="top_attach">5</property>
+		  <property name="bottom_attach">6</property>
+		  <property name="x_options">fill</property>
 		  <property name="y_options"></property>
 		</packing>
 	      </child>
+
 	    </widget>
 	    <packing>
 	      <property name="padding">0</property>
_______________________________________________
Anaconda-devel-list mailing list
Anaconda-devel-list@xxxxxxxxxx
https://www.redhat.com/mailman/listinfo/anaconda-devel-list

[Index of Archives]     [Kickstart]     [Fedora Users]     [Fedora Legacy List]     [Fedora Maintainers]     [Fedora Desktop]     [Fedora SELinux]     [Big List of Linux Books]     [Yosemite News]     [Yosemite Photos]     [KDE Users]     [Fedora Tools]
  Powered by Linux