7054440 Allow combination of name services to be configured in S11 text installer: DNS+NIS, DNS+LDAP
authorWilliam Schumann <william.schumann@sun.com>
Thu, 14 Jul 2011 11:33:34 -0600
changeset 1281 1e322933782d
parent 1280 e0e9dc6ef46b
child 1282 c11cfe88c3da
7054440 Allow combination of name services to be configured in S11 text installer: DNS+NIS, DNS+LDAP
usr/src/cmd/system-config/__init__.py
usr/src/cmd/system-config/nameservice.py
usr/src/cmd/system-config/profile/__init__.py
usr/src/cmd/system-config/profile/nameservice_info.py
usr/src/cmd/system-config/profile/test/test_nameservice_info.py
usr/src/cmd/system-config/profile/user_info.py
usr/src/cmd/system-config/summary.py
usr/src/cmd/system-config/test/test_nameservice.py
usr/src/cmd/text-install/summary.py
--- a/usr/src/cmd/system-config/__init__.py	Thu Jul 14 09:36:37 2011 -0700
+++ b/usr/src/cmd/system-config/__init__.py	Thu Jul 14 11:33:34 2011 -0600
@@ -109,7 +109,8 @@
 from solaris_install.sysconfig.profile import ConfigProfile, SMFConfig, \
                                               SMFInstance, SMFPropertyGroup, \
                                               SMFProperty
-from solaris_install.sysconfig.nameservice import NSChooser, NSDomain, \
+from solaris_install.sysconfig.nameservice import NSDNSChooser, NSAltChooser, \
+                                                  NSDomain, \
                                                   NSDNSServer, NSDNSSearch, \
                                                   NSLDAPProfile, \
                                                   NSLDAPProxyBindChooser, \
@@ -227,7 +228,8 @@
 
 def _append_nameservice_screens(result, main_win):
     ''' Initialize and append all name service screens '''
-    result.append(NSChooser(main_win))
+    result.append(NSDNSChooser(main_win))
+    result.append(NSAltChooser(main_win))
     result.append(NSDomain(main_win))
     result.append(NSDNSServer(main_win))
     result.append(NSDNSSearch(main_win))
--- a/usr/src/cmd/system-config/nameservice.py	Thu Jul 14 09:36:37 2011 -0700
+++ b/usr/src/cmd/system-config/nameservice.py	Thu Jul 14 11:33:34 2011 -0600
@@ -65,17 +65,23 @@
     # dimensions
     SCROLL_SIZE = 2
     BORDER_WIDTH = (0, 3)
+    HOSTNAME_SCREEN_LEN = 25
     # name service choices for display to user
-    USER_CHOICE_LIST = [_('DNS'), _('LDAP'), _('NIS'), _('None')]
+    USER_CHOICE_LIST = [_('None'), _('LDAP'), _('NIS')]
+    USER_CHOICE_DNS = _('DNS')
     # identify name service choices for internal use
-    CHOICE_LIST = ['DNS', 'LDAP', 'NIS', None]
+    CHOICE_LIST = [None, 'LDAP', 'NIS']
 
+    MSG_HOST_NAME = _("Enter either a host name or an IP address.")
+    MSG_IP_FMT = _("An IP address must be of the form xxx.xxx.xxx.xxx")
+ 
     def __init__(self, main_win, screen=None):
         global LOGGER
         if LOGGER is None:
             LOGGER = logging.getLogger(INSTALL_LOGGER_NAME + ".sysconfig")
         super(NameService, self).__init__(main_win)
-        self.cur_nschoice_idx = self.CHOICE_LIST.index("DNS")
+        self.cur_dnschoice_idx = 0
+        self.cur_nschoice_idx = self.CHOICE_LIST.index(None)
         self.cur_pbchoice_idx = NameServiceInfo.LDAP_CHOICE_NO_PROXY_BIND
         self.cur_nisnschoice_idx = NameServiceInfo.NIS_CHOICE_AUTO
         self.intro = "DEVELOPER: define intro in subclass"
@@ -94,21 +100,24 @@
     def _show(self):
         ''' called upon display of a screen '''
         sc_profile = solaris_install.sysconfig.profile.from_engine()
-        if sc_profile.nic.type != NetworkInfo.MANUAL and \
+        LOGGER.debug(sc_profile)
+        if hasattr(sc_profile, 'nic') and sc_profile.nic and \
+                sc_profile.nic.type != NetworkInfo.MANUAL and \
                 configure_group(SC_GROUP_NETWORK):
             raise SkipException
         if sc_profile.nameservice is None:
             # first time, assign sysconfig values to defaults found above
             LOGGER.debug('assigning NSV to sysconfig.profile')
             sc_profile.nameservice = NameServiceInfo()
-            nic = sc_profile.nic
-            LOGGER.info("Found NIC:")
-            LOGGER.info(nic)
-            # if values were learned from the NIC, offer those as defaults
-            if nic.domain:
-                sc_profile.nameservice.domain = nic.domain
-            if nic.dns_address:
-                sc_profile.nameservice.dns_server = nic.dns_address
+            if hasattr(sc_profile, 'nic') and sc_profile.nic:
+                nic = sc_profile.nic
+                LOGGER.info("Found NIC:")
+                LOGGER.info(nic)
+                # if values were learned from the NIC, offer those as defaults
+                if nic.domain:
+                    sc_profile.nameservice.domain = nic.domain
+                if nic.dns_address:
+                    sc_profile.nameservice.dns_server = nic.dns_address
         self.nameservice = sc_profile.nameservice
 
     def _paint_opening(self):
@@ -118,25 +127,70 @@
         return 2 + self.center_win.add_paragraph(self.intro, 1)
 
 
-class NSChooser(NameService):
+class NSDNSChooser(NameService):
 
-    HEADER_TEXT = _("Name Service")
+    HEADER_TEXT = _("DNS Name Service")
     HELP_DATA = (SCI_HELP + "/%s/name_service.txt", HEADER_TEXT)
     HELP_FORMAT = "%s"
 
     def __init__(self, main_win):
-        super(NSChooser, self).__init__(main_win)
-        LOGGER.debug('in NSChooser init')
+        super(NSDNSChooser, self).__init__(main_win)
+        LOGGER.debug('in NSDNSChooser init')
         self.intro = \
-                _("Select the name service that will be used by this "
-                  "system. Select None if the desired name service is not "
-                  "listed.")
+                _("Indicates whether or not the system should use the DNS "
+                  "name service.")
 
     def _show(self):
         ''' called upon display of a screen '''
-        super(NSChooser, self)._show()
+        super(NSDNSChooser, self)._show()
         y_loc = self._paint_opening()
         LOGGER.debug(self.nameservice)
+        # allow the user to choose DNS or not
+        ynlist = [_('Configure DNS'),
+                  _('Do not configure DNS')]
+        area = WindowArea(x_loc=0, y_loc=y_loc,
+                          scrollable_lines=len(ynlist) + 1)
+        area.lines = self.win_size_y - (y_loc + 1)
+        area.columns = self.win_size_x
+        self.scroll_region_dns = ScrollWindow(area, window=self.center_win)
+        # add the entries to the screen
+        for idx, yon in enumerate(ynlist):
+            win_area = WindowArea(1, textwidth(yon) + 1, idx, INDENT)
+            ListItem(win_area, window=self.scroll_region_dns, text=yon,
+                     data_obj=yon)
+        # finalize positioning
+        self.main_win.do_update()
+        self.center_win.activate_object(self.scroll_region_dns)
+        self.scroll_region_dns.activate_object_force(self.cur_dnschoice_idx,
+                                                 force_to_top=True)
+
+    def on_change_screen(self):
+        ''' called when changes submitted by user for all screens '''
+        # Save the chosen index and object when leaving the screen
+        self.cur_dnschoice_idx = self.scroll_region_dns.active_object
+        self.nameservice.dns = (self.cur_dnschoice_idx == 0)
+        LOGGER.info("on_change_screen DNS chosen? %s", self.nameservice.dns)
+
+
+class NSAltChooser(NameService):
+
+    HEADER_TEXT = _("Alternate Name Service")
+    HELP_DATA = (SCI_HELP + "/%s/name_service.txt", HEADER_TEXT)
+
+    def __init__(self, main_win):
+        super(NSAltChooser, self).__init__(main_win)
+        self.intro = \
+                _("From the list below, select one name service to be "
+                  "used by this system. If the desired name service is not "
+                  "listed, select None. The selected name service may be "
+                  "used in conjunction with DNS.")
+
+    def _show(self):
+        ''' called upon display of a screen '''
+        super(NSAltChooser, self)._show()
+        y_loc = self._paint_opening()
+        LOGGER.debug(self.nameservice)
+        # allow the user to select an alternate name service
         area = WindowArea(x_loc=0, y_loc=y_loc,
                         scrollable_lines=len(NameService.USER_CHOICE_LIST) + 1)
         area.lines = self.win_size_y - (y_loc + 1)
@@ -150,6 +204,7 @@
             win_area = WindowArea(1, hilite, idx, INDENT)
             ListItem(win_area, window=self.scroll_region, text=nsn,
                      data_obj=nsn)
+        # finalize positioning
         self.main_win.do_update()
         self.center_win.activate_object(self.scroll_region)
         self.scroll_region.activate_object_force(self.cur_nschoice_idx,
@@ -180,7 +235,9 @@
     def _show(self):
         ''' show domain '''
         super(NSDomain, self)._show()
-        if self.nameservice.nameservice is None:
+        if not _has_name_service():
+            raise SkipException
+        if not self.nameservice.dns and not self.nameservice.nameservice:
             raise SkipException
         y_loc = self._paint_opening()
         cols = min(MAXDOMAINLEN + 1,
@@ -199,26 +256,30 @@
         validate_domain(self.domain.get_text(), allow_empty=False)
 
     def on_change_screen(self):
-        self.nameservice.domain = self.domain.get_text()
-        # default in LDAP-formatted values for domain
-        if self.nameservice.nameservice == 'LDAP':
-            ns = self.nameservice
-            ldapdom = _convert_to_ldap_domain(ns.domain)
-            # default in search base from domain
-            if not ns.ldap_search_base or \
-                    not ns.ldap_search_base.startswith(ldapdom):
-                ns.ldap_search_base = ldapdom
-            # default in distinguished name from search base 
-            if not ns.ldap_pb_dn:
-                # provide probable DN default
-                ns.ldap_pb_dn = 'cn=proxyagent,ou=profile,' + \
-                        ns.ldap_search_base
-            elif not ns.ldap_pb_dn.endswith(ns.ldap_search_base):
-                # user changed search base, update DN
-                dnsplit = ns.ldap_pb_dn.split(',dc=')
-                # replace old search base with new
-                if len(dnsplit) > 0 and dnsplit[0]:
-                    ns.ldap_pb_dn = dnsplit[0] + ',' + ns.ldap_search_base
+        ns = self.nameservice
+        new_domain = self.domain.get_text()
+        if ns.domain != new_domain or \
+                (ns.nameservice == 'LDAP' and not ns.ldap_search_base):
+            ns.domain = new_domain
+            # default in LDAP-formatted values for domain
+            if self.nameservice.nameservice == 'LDAP':
+                ldapdom = _convert_to_ldap_domain(new_domain)
+                # default in search base from domain
+                if not ns.ldap_search_base or \
+                        not ns.ldap_search_base.startswith(ldapdom):
+                    ns.ldap_search_base = ldapdom
+                # base DN on search base
+                if ns.ldap_pb_dn:
+                    # update DN with any changes in search_base from user
+                    fixedbase = _ldap_domain_fixup(ns.ldap_pb_dn,
+                            ns.ldap_search_base)
+                    if fixedbase:
+                        # user changed search base, update DN
+                        ns.ldap_pb_dn = fixedbase
+                else:
+                    # provide probable DN default
+                    ns.ldap_pb_dn = 'cn=proxyagent,ou=profile,' + \
+                            ns.ldap_search_base
 
 
 class NSDNSServer(NameService):
@@ -236,7 +297,7 @@
     def _show(self):
         super(NSDNSServer, self)._show()
         # check dictionary of screens associated with name service selections
-        if self.nameservice.nameservice != 'DNS':
+        if not self.nameservice.dns:
             raise SkipException
         y_loc = self._paint_opening()
         self.dns_server_list = []
@@ -303,7 +364,7 @@
         ''' show DNS search list '''
         super(NSDNSSearch, self)._show()
         # check dictionary of screens associated with name service selections
-        if self.nameservice.nameservice != 'DNS':
+        if not self.nameservice.dns:
             raise SkipException
         y_loc = self._paint_opening()
         cols = min(MAXDOMAINLEN + 1,
@@ -363,23 +424,31 @@
 
     def __init__(self, main_win):
         super(NSLDAPProfile, self).__init__(main_win)
-        self.intro = \
-                _("Specify the name of the LDAP profile to be used to "
-                  "configure this system and the IP address of the "
-                  "server that contains the profile.")
         self.title = _("Profile name:")
-        self.title2 = _("Profile server IP address:")
         self.title3 = _("Search base:")
 
     def _show(self):
         super(NSLDAPProfile, self)._show()
         if self.nameservice.nameservice != 'LDAP':
             raise SkipException
+        if self.nameservice.dns:
+            self.intro = \
+                _("Specify the name of the LDAP profile to be used to "
+                  "configure this system and the host name or IP address of "
+                  "the server that contains the profile.")
+            self.title2 = _("Profile server host name or IP address:")
+        else:
+            self.intro = \
+                _("Specify the name of the LDAP profile to be used to "
+                  "configure this system and the IP address of the "
+                  "server that contains the profile.")
+            self.title2 = _("Profile server IP address:")
+        self.intro += _("  Enter the LDAP search base.")
         y_loc = self._paint_opening()
-        maxtitlelen = max(max(textwidth(self.title), textwidth(self.title2)),
+        maxtitlelen = max(textwidth(self.title), textwidth(self.title2),
                           textwidth(self.title3))
         aligned_x_loc = maxtitlelen + INDENT + 1
-        cols = self.win_size_x - maxtitlelen - INDENT - 1
+        cols = self.win_size_x - aligned_x_loc
         self.center_win.add_text(self.title.rjust(maxtitlelen), y_loc, INDENT)
         area = WindowArea(1, cols, y_loc, aligned_x_loc)
         self.ldap_profile = EditField(area, window=self.center_win,
@@ -389,12 +458,17 @@
         # in case of error, tell user what is being validated
         self.ldap_profile.validate_kwargs['etext'] = _('profile name')
         y_loc += 1
-        area = WindowArea(1, MAXIP, y_loc, aligned_x_loc)
+        area = WindowArea(1, cols, y_loc, aligned_x_loc,
+                        scrollable_columns=NameService.HOSTNAME_SCREEN_LEN + 1)
         self.center_win.add_text(self.title2.rjust(maxtitlelen), y_loc, INDENT)
+        # create edit field, validating for host name or IP address depending
+        # on whether DNS was selected
         self.ldap_ip = EditField(area, window=self.center_win,
                                  text=self.nameservice.ldap_ip,
-                                 validate=incremental_validate_ip,
-                                 error_win=self.main_win.error_line)
+                                 error_win=self.main_win.error_line,
+                                 validate=(incremental_validate_host
+                                           if self.nameservice.dns
+                                           else incremental_validate_ip))
         # search base
         y_loc += 1
         self.center_win.add_text(self.title3.rjust(maxtitlelen), y_loc, INDENT)
@@ -408,23 +482,27 @@
 
     def validate(self):
         validate_ldap_profile(self.ldap_profile.get_text())
-        validate_ip(self.ldap_ip.get_text())
+        ldap_ip = self.ldap_ip.get_text()
+        if self.nameservice.dns:
+            validate_host_or_ip(ldap_ip)
+        else:
+            validate_ip(ldap_ip)
         if not self.ldap_profile.get_text():
             raise UIMessage(_("The LDAP profile name cannot be blank."))
-        if not self.ldap_ip.get_text():
+        if not ldap_ip:
             raise UIMessage(_("The LDAP server IP address cannot be blank."))
 
     def on_change_screen(self):
         self.nameservice.ldap_profile = self.ldap_profile.get_text()
         self.nameservice.ldap_ip = self.ldap_ip.get_text()
-        self.nameservice.ldap_search_base = self.ldap_search_base.get_text()
-        # update DN with any changes in search_base from user
-        ldap_search_base = self.nameservice.ldap_search_base
-        if not self.nameservice.ldap_pb_dn.endswith(ldap_search_base):
-            dnsplit = self.nameservice.ldap_pb_dn.split(',dc=')
-            if len(dnsplit) > 0 and dnsplit[0]:
-                self.nameservice.ldap_pb_dn = dnsplit[0] + ',' + \
-                        ldap_search_base
+        new_search_base = self.ldap_search_base.get_text()
+        if new_search_base != self.nameservice.ldap_search_base:
+            self.nameservice.ldap_search_base = new_search_base
+            # update DN with any changes in search_base from user
+            fixedbase = _ldap_domain_fixup(self.nameservice.ldap_pb_dn,
+                                           new_search_base)
+            if fixedbase:
+                self.nameservice.ldap_pb_dn = fixedbase
 
 
 class NSLDAPProxyBindChooser(NameService):
@@ -455,9 +533,9 @@
             win_area = WindowArea(1, textwidth(yon) + 1, idx, INDENT)
             ListItem(win_area, window=self.scroll_region, text=yon,
                      data_obj=yon)
-            self.main_win.do_update()
-            self.center_win.activate_object(self.scroll_region)
-            self.scroll_region.activate_object_force(self.cur_pbchoice_idx,
+        self.main_win.do_update()
+        self.center_win.activate_object(self.scroll_region)
+        self.scroll_region.activate_object_force(self.cur_pbchoice_idx,
                                                      force_to_top=True)
 
     def on_change_screen(self):
@@ -585,35 +663,54 @@
 
     def __init__(self, main_win):
         super(NSNISIP, self).__init__(main_win)
-        self.intro = \
-                _("Enter the IP address of the name server.  IP "
-                  "addresses must contain four sets of numbers separated "
-                  "by periods (for example, 129.200.9.1).")
-        self.title = _("Server's IP address:")
 
     def _show(self):
         super(NSNISIP, self)._show()
+        LOGGER.info("self.nameservice: %s" % self.nameservice)
         if self.nameservice.nameservice != 'NIS':
             raise SkipException
         if self.nameservice.nis_auto == NameServiceInfo.NIS_CHOICE_AUTO:
             raise SkipException
+        if self.nameservice.dns:
+            self.intro = \
+                _("Enter the host name or IP address of the name server.  "
+                  "A host name must have at least 2 characters and can be "
+                  "alphanumeric and can contain hyphens.  IP "
+                  "addresses must contain four sets of numbers separated "
+                  "by periods (for example, 129.200.9.1).")
+            self.title = _("Server's host name or IP address:")
+        else:
+            self.intro = \
+                _("Enter the IP address of the name server.  IP "
+                  "addresses must contain four sets of numbers separated "
+                  "by periods (for example, 129.200.9.1).")
+            self.title = _("Server's IP address:")
         y_loc = self._paint_opening()
         self.center_win.add_text(self.title, y_loc, INDENT)
-        maxtitlelen = textwidth(self.title)
-        cols = self.win_size_x - maxtitlelen - INDENT - 1
-        area = WindowArea(1, cols, y_loc, maxtitlelen + INDENT + 1)
+        aligned_x_loc = textwidth(self.title) + INDENT + 1
+        cols = self.win_size_x - aligned_x_loc
+        area = WindowArea(1, cols, y_loc, aligned_x_loc)
         self.center_win.add_text(self.title, y_loc, INDENT)
-        area = WindowArea(1, MAXIP, y_loc, maxtitlelen + INDENT + 1)
+        area = WindowArea(1, cols, y_loc, aligned_x_loc,
+                        scrollable_columns=NameService.HOSTNAME_SCREEN_LEN + 1)
+        # create edit field, validating for host name or IP address depending
+        # on whether DNS was selected
         self.nis_ip = EditField(area, window=self.center_win,
                                 text=self.nameservice.nis_ip,
-                                validate=incremental_validate_ip,
-                                error_win=self.main_win.error_line)
+                                error_win=self.main_win.error_line,
+                                validate=(incremental_validate_host
+                                          if self.nameservice.dns
+                                          else incremental_validate_ip))
         self.main_win.do_update()
         self.center_win.activate_object(self.nis_ip)
 
     def validate(self):
-        validate_ip(self.nis_ip.get_text())
-        if not self.nis_ip.get_text():
+        nis_ip = self.nis_ip.get_text()
+        if self.nameservice.dns:
+            validate_host_or_ip(nis_ip)
+        else:
+            validate_ip(nis_ip)
+        if not nis_ip:
             raise UIMessage(_("The NIS server IP address cannot be blank."))
 
     def on_change_screen(self):
@@ -667,16 +764,36 @@
                               "quotation marks."))
 
 
+def validate_host_or_ip(host_name):
+    '''Validate argument as either a valid hostname or IP address
+    Raises: UIMessage if not valid
+    '''
+    if not host_name:
+        return
+    # assume host name if input starts with alpha character
+    if host_name[0].isalpha():
+        for chr in host_name:
+            if not chr.isalnum() and not chr in u"-.":
+                raise UIMessage(_("A host name can only contain letters, "
+                                  "numbers,  periods, and minus signs (-)."))
+        return
+    # attempt validation as a numeric IP address
+    try:
+        IPAddress.convert_address(host_name)
+    except ValueError:
+        raise UIMessage(NameService.MSG_HOST_NAME)
+
+
 def validate_ip(ip_address):
     '''Wrap a call to IPAddress.check_address and raise a UIMessage with
     appropriate message text
     '''
     if not ip_address:
-        return True
+        return
     try:
         IPAddress.convert_address(ip_address)
     except ValueError:
-        raise UIMessage(_("An IP address must be of the form xxx.xxx.xxx.xxx"))
+        raise UIMessage(NameService.MSG_IP_FMT)
 
 
 def validate_domain(domain, allow_empty=True):
@@ -712,7 +829,30 @@
     try:
         IPAddress.incremental_check(ip_address)
     except ValueError:
-        raise UIMessage(_("An IP address must be of the form xxx.xxx.xxx.xxx"))
+        raise UIMessage(NameService.MSG_IP_FMT)
+    return True
+
+
+def incremental_validate_host(edit_field):
+    '''Incrementally validate the host as the user enters it
+    Arg: edit_field - EditField object for validation
+    Raises: UIMessage on failure
+    '''
+    host_name = edit_field.get_text()
+    if not host_name:
+        return True
+    # assume host name if input starts with alpha character
+    if host_name[0].isalpha():
+        for chr in host_name:
+            if not chr.isalnum() and not chr in u"-.":
+                raise UIMessage(_("A host name can only contain letters, "
+                                  "numbers,  periods, and minus signs (-)."))
+        return True
+    # attempt validation as a numeric IP address
+    try:
+        IPAddress.incremental_check(host_name)
+    except ValueError:
+        raise UIMessage(NameService.MSG_HOST_NAME)
     return True
 
 
@@ -748,6 +888,15 @@
             raise UIMessage(_('Invalid character for domain name.'))
 
 
+def _has_name_service():
+        nsv = solaris_install.sysconfig.profile.from_engine().nameservice
+        if nsv.dns:
+            return True
+        if nsv.nameservice:
+            return True
+        return False
+
+
 def _convert_to_ldap_domain(domain):
     ''' given a domain in dotted notation, produce an LDAP domain
     Arg: domain - domain to convert
@@ -757,3 +906,18 @@
     for label in domain.split('.'):
         labels.append('dc=' + label)
     return ','.join(labels)
+
+
+def _ldap_domain_fixup(old, new_search_base):
+    ''' if existing LDAP-formatted value, does not have the specified
+    search base, replace it with the specified search base
+    Args:
+        old - the existing LDAP-formatted value
+        new_search_base - the search base to replace it with
+    '''
+    if old.endswith(new_search_base):
+        return None
+    dnsplit = old.split(',dc=')
+    if len(dnsplit) > 0 and dnsplit[0]:
+        return dnsplit[0] + ',' + new_search_base
+    return None
--- a/usr/src/cmd/system-config/profile/__init__.py	Thu Jul 14 09:36:37 2011 -0700
+++ b/usr/src/cmd/system-config/profile/__init__.py	Thu Jul 14 11:33:34 2011 -0600
@@ -325,7 +325,10 @@
                     int(propval)
                     proptype = "count"
                 except:
-                    proptype = "astring"
+                    if iproptype == "host":
+                        proptype = iproptype
+                    else:
+                        proptype = "astring"
 
         if is_list:
             proptype += "_list"
--- a/usr/src/cmd/system-config/profile/nameservice_info.py	Thu Jul 14 09:36:37 2011 -0700
+++ b/usr/src/cmd/system-config/profile/nameservice_info.py	Thu Jul 14 11:33:34 2011 -0600
@@ -58,7 +58,7 @@
     LDAP_CHOICE_PROXY_BIND = 1
 
     def __init__(self, nameservice=None, domain='',
-                 dns_server=[], dns_search=[],
+                 dns=True, dns_server=[], dns_search=[],
                  ldap_profile='default', ldap_ip='', ldap_search_base='',
                  ldap_proxy_bind=LDAP_CHOICE_NO_PROXY_BIND, ldap_pb_dn='',
                  ldap_pb_psw='', nis_ip='', nis_auto=NIS_CHOICE_AUTO):
@@ -66,6 +66,7 @@
         self.nameservice = nameservice
         self.domain = domain
         # DNS-specific
+        self.dns = dns
         self.dns_server = dns_server
         self.dns_search = dns_search
         # LDAP-specific
@@ -82,6 +83,7 @@
     def __repr__(self):
         return '\n'.join(["NS %s:" % self.nameservice,
                           "Domain: %s" % self.domain,
+                          "DNS? %s" % self.dns,
                           "DNSserv: %s" % self.dns_server,
                           "DNSsearch: %s" % self.dns_search,
                           "LDAPprofname: %s" % self.ldap_profile,
@@ -95,18 +97,18 @@
 
     def to_xml(self):
         data_objects = []
-        if self.nameservice is None:
+        if not self.dns and self.nameservice is None:
             # if no name services, files only
             LOGGER().info('setting name service to files only')
         # configure svc:system/name-service/switch
         LOGGER().info('preparing profile with nsswitch')
         # set NS switch service objects according to user's selection
-        data_objects.append(_set_nsswitch(self.nameservice))
+        data_objects.append(_set_nsswitch(self.dns, self.nameservice))
         # enable name service cache
         data_objects.append(_enable_service('system/name-service/cache'))
         LOGGER().debug('to_xml:name service type=%s', self.nameservice)
         LOGGER().info(self)
-        if self.nameservice == 'DNS':
+        if self.dns:
             LOGGER().info('preparing profile for DNS')
             dns = SMFConfig('network/dns/client')
             data_objects.append(dns)
@@ -197,7 +199,7 @@
                 # manual configuration naming NIS server explicitly
                 if self.nis_auto == self.NIS_CHOICE_MANUAL and \
                         self.nameservice == 'NIS':
-                    proptype = 'net_address'
+                    proptype = 'host'
                     nis_ip = nis_props.setprop("property", "ypservers",
                                                proptype)
                     nis_ip.add_value_list(propvals=[self.nis_ip],
@@ -229,7 +231,7 @@
         return False
 
 
-def _set_nsswitch(nameservice):
+def _set_nsswitch(dns, nameservice):
     ''' configure name services switch table
     for svc: system/name-service/switch
     Arg:
@@ -242,23 +244,37 @@
     props = SMFPropertyGroup('config')
     svc.insert_children([props])
     # set name service sources per name service
-    source_dict = {
-            'DNS': {
-                'default': 'files',
-                'host': 'files dns',
-                'printer': 'user files'},
-            'LDAP': {
-                'default': 'files ldap',
-                'printer': 'user files ldap',
-                'netgroup': 'ldap'},
-            'NIS': {
-                'default': 'files nis',
-                'printer': 'user files nis',
-                'netgroup': 'nis'},
-            None: {
-                'default': 'files',
-                'printer': 'user files'}
-            }[nameservice]
+    if dns:
+        # set combination with DNS
+        source_dict = {
+                None: {
+                    'default': 'files',
+                    'host': 'files dns',
+                    'printer': 'user files'},
+                'LDAP': {
+                    'default': 'files ldap',
+                    'host': 'files dns',
+                    'printer': 'user files ldap'},
+                'NIS': {
+                    'default': 'files nis',
+                    'host': 'files dns',
+                    'printer': 'user files nis'}
+                }[nameservice]
+    else:
+        # set name service sources per name service
+        source_dict = {
+                None: {
+                    'default': 'files',
+                    'printer': 'user files'},
+                'LDAP': {
+                    'default': 'files ldap',
+                    'printer': 'user files ldap',
+                    'netgroup': 'ldap'},
+                'NIS': {
+                    'default': 'files nis',
+                    'printer': 'user files nis',
+                    'netgroup': 'nis'}
+                }[nameservice]
     for prop in source_dict:
         props.setprop('propval', prop, 'astring', source_dict[prop])
     # configure default service instance
--- a/usr/src/cmd/system-config/profile/test/test_nameservice_info.py	Thu Jul 14 09:36:37 2011 -0700
+++ b/usr/src/cmd/system-config/profile/test/test_nameservice_info.py	Thu Jul 14 11:33:34 2011 -0600
@@ -156,13 +156,15 @@
     def test_to_xml_no_name_service(self):
         '''Test SCI tool name service to_xml method - no name service'''
         self._gen_to_xml(NameServiceInfo(
+                         dns=False,
                          domain='my.domain.com',
                          dns_server=['1.1.1.1'], dns_search=['my.domain.com']),
                          SAMPLE_NONE_XML)
 
     def test_to_xml_dns(self):
         '''Test SCI tool name service to_xml method - DNS'''
-        self._gen_to_xml(NameServiceInfo(nameservice='DNS',
+        self._gen_to_xml(NameServiceInfo(
+                         dns=True,
                          domain='my.domain.com',
                          dns_server=['1.1.1.1'], dns_search=['my.domain.com']),
                          SAMPLE_DNS_XML)
@@ -170,15 +172,17 @@
     def test_to_xml_ldap(self):
         '''Test SCI tool name service to_xml method - LDAP'''
         self._gen_to_xml(NameServiceInfo(
+                         dns=False,
                          domain='my.domain.com',
                          nameservice='LDAP', ldap_ip='1.1.1.1'),
                          SAMPLE_LDAP_XML)
 
     def test_to_xml_nis(self):
         '''Test SCI tool name service to_xml method - NIS'''
-        self._gen_to_xml(NameServiceInfo(nameservice='NIS', nis_ip='1.1.1.1',
+        self._gen_to_xml(NameServiceInfo(
+                         dns=False,
                          domain='my.domain.com',
-                         nis_auto=1),
+                         nameservice='NIS', nis_ip='1.1.1.1', nis_auto=1),
                          SAMPLE_NIS_XML)
 
     def _gen_to_xml(self, nsv, compare_with_this):
--- a/usr/src/cmd/system-config/profile/user_info.py	Thu Jul 14 09:36:37 2011 -0700
+++ b/usr/src/cmd/system-config/profile/user_info.py	Thu Jul 14 11:33:34 2011 -0600
@@ -175,7 +175,7 @@
 
             # Expire
             if self.expire is not None:
-                self.add_props(expire = str(self.expire))
+                self.add_props(expire=str(self.expire))
         else:
             self.pg_name = "user_account"
             #
@@ -192,7 +192,7 @@
 
             # Expire
             if self.expire is not None:
-                self.add_props(expire = str(self.expire))
+                self.add_props(expire=str(self.expire))
 
             # Description
             if self.real_name:
@@ -232,6 +232,7 @@
     def can_handle(cls, xml_node):
         return False
 
+
 def validate_username(user_str, blank_ok=True):
     '''Ensure username complies with following rules
        - username can contain characters from set of alphabetic characters,
@@ -251,7 +252,6 @@
     if not user_str:
         raise UsernameInvalid(_("Username must not be blank"))
 
-
     # verify that username starts with alphabetic character
     if not user_str[0].isalpha():
         raise UsernameInvalid(_("Username must start with a letter"))
@@ -276,6 +276,7 @@
         # case, it's safe to apply
         return True
 
+
 def validate_password(password):
     '''validates the password entered'''
     # check the length
--- a/usr/src/cmd/system-config/summary.py	Thu Jul 14 09:36:37 2011 -0700
+++ b/usr/src/cmd/system-config/summary.py	Thu Jul 14 11:33:34 2011 -0600
@@ -141,8 +141,9 @@
                                     self.sysconfig.system.keyboard)
                 summary_text.append("")
 
-            summary_text.append(_("Terminal type: %s") %
-                                self.sysconfig.system.terminal_type)
+            if hasattr(self.sysconfig.system, 'terminal_type'):
+                summary_text.append(_("Terminal type: %s") %
+                                    self.sysconfig.system.terminal_type)
 
             # user/root accounts belong to SC_GROUP_USERS group
             if configure_group(SC_GROUP_USERS):
@@ -156,6 +157,8 @@
                 summary_text.append("")
                 summary_text.append(_("Network:"))
                 summary_text.extend(self.get_networks())
+            elif configure_group(SC_GROUP_NS):
+                self._get_nameservice(summary_text)
         
             return "\n".join(summary_text)
 
@@ -177,19 +180,22 @@
             return network_summary
 
         nic = self.sysconfig.nic       
-        if nic.type == NetworkInfo.AUTOMATIC:
-            network_summary.append(_("  Network Configuration: Automatic"))
-        elif nic.type == NetworkInfo.NONE:
-            network_summary.append(_("  Network Configuration: None"))
-        else:
-            network_summary.append(_("  Manual Configuration: %s")
-                                   % nic.nic_name)
-            network_summary.append(_("IP Address: %s") % nic.ip_address)
-            network_summary.append(_("Netmask: %s") % nic.netmask)
-            if nic.gateway:
-                network_summary.append(_("Router: %s") % nic.gateway)
-            if configure_group(SC_GROUP_NS):
-                self._get_nameservice(network_summary)
+        if nic:
+            if nic.type == NetworkInfo.AUTOMATIC:
+                network_summary.append(_("  Network Configuration: Automatic"))
+            elif nic.type == NetworkInfo.NONE:
+                network_summary.append(_("  Network Configuration: None"))
+            else:
+                network_summary.append(_("  Manual Configuration: %s")
+                                       % nic.nic_name)
+                network_summary.append(_("IP Address: %s") % nic.ip_address)
+                network_summary.append(_("Netmask: %s") % nic.netmask)
+                if nic.gateway:
+                    network_summary.append(_("Router: %s") % nic.gateway)
+                if configure_group(SC_GROUP_NS):
+                    self._get_nameservice(network_summary)
+        elif configure_group(SC_GROUP_NS):
+            self._get_nameservice(network_summary)
         return network_summary
 
     def _get_nameservice(self, summary):
@@ -197,29 +203,35 @@
         if not self.sysconfig.nameservice:
             return
         nameservice = self.sysconfig.nameservice
-        if nameservice.nameservice and nameservice.domain:
+        if not nameservice.dns and not nameservice.nameservice:
+            return
+        if nameservice.domain:
             summary.append(_("Domain: %s") % nameservice.domain)
         # fetch localized name for name service
-        ns_idx = NameService.CHOICE_LIST.index(nameservice.nameservice)
-        summary.append(_("Name service: %s") %
-                NameService.USER_CHOICE_LIST[ns_idx])
-        if nameservice.nameservice == 'DNS':
+        if nameservice.dns:
+            summary.append(_("Name service: %s") % NameService.USER_CHOICE_DNS)
             # strip empty list entries
             dnslist = [ln for ln in nameservice.dns_server if ln]
             summary.append(_("DNS servers: ") + " ".join(dnslist))
             dnslist = [ln for ln in nameservice.dns_search if ln]
-            summary.append(_("Domain list: ") + " ".join(dnslist))
-        elif nameservice.nameservice == 'LDAP':
+            summary.append(_("DNS Domain search list: ") + " ".join(dnslist))
+        if nameservice.nameservice == 'LDAP':
+            ns_idx = NameService.CHOICE_LIST.index(nameservice.nameservice)
+            summary.append(_("Name service: %s") %
+                           NameService.USER_CHOICE_LIST[ns_idx])
             summary.append(_("LDAP profile: ") + nameservice.ldap_profile)
             summary.append(_("LDAP server's IP: ") + nameservice.ldap_ip)
             summary.append(_("LDAP search base: ") + 
-                    nameservice.ldap_search_base)
+                           nameservice.ldap_search_base)
             if nameservice.ldap_proxy_bind == \
                     NameServiceInfo.LDAP_CHOICE_PROXY_BIND:
                 summary.append(_("LDAP proxy bind distinguished name: ") +
                                nameservice.ldap_pb_dn)
                 summary.append(_("LDAP proxy bind password: [concealed]"))
         elif nameservice.nameservice == 'NIS':
+            ns_idx = NameService.CHOICE_LIST.index(nameservice.nameservice)
+            summary.append(_("Name service: %s") %
+                           NameService.USER_CHOICE_LIST[ns_idx])
             if nameservice.nis_auto == NameServiceInfo.NIS_CHOICE_AUTO:
                 summary.append(_("NIS server: broadcast"))
             elif nameservice.nis_ip:
--- a/usr/src/cmd/system-config/test/test_nameservice.py	Thu Jul 14 09:36:37 2011 -0700
+++ b/usr/src/cmd/system-config/test/test_nameservice.py	Thu Jul 14 11:33:34 2011 -0600
@@ -34,6 +34,7 @@
 from solaris_install.sysconfig.nameservice import NSDomain, NSDNSServer, \
         NSDNSSearch, NSLDAPProfile, NSLDAPProxyBindInfo, NSNISIP
 import solaris_install.sysconfig.nameservice as nsv
+from solaris_install.sysconfig.profile.nameservice_info import NameServiceInfo
 from terminalui.base_screen import UIMessage
 
 
@@ -50,13 +51,14 @@
     '''Test Name Services screens'''
     
     def setUp(self):
+        self.NameServiceInfo__init__ = NameServiceInfo.__init__ 
         self.NSDomain__init__ = NSDomain.__init__ 
         self.NSDNSServer__init__ = NSDNSServer.__init__ 
         self.NSDNSSEARCH__init__ = NSDNSSearch.__init__ 
         self.NSLDAPProfile__init__ = NSLDAPProfile.__init__ 
         self.NSLDAPProxyBindInfo_init_ = NSLDAPProxyBindInfo.__init__ 
         self.NSNISIP__init__ = NSNISIP.__init__ 
-        NSNISIP.__init__ = self.NSNISIP__init__
+        NameServiceInfo.__init__ = lambda x, y: None
         NSDomain.__init__ = lambda x, y: None
         NSDNSServer.__init__ = lambda x, y: None
         NSDNSSearch.__init__ = lambda x, y: None
@@ -67,10 +69,15 @@
         self.ns_dnsserver = NSDNSServer(None)
         self.ns_dnssearch = NSDNSSearch(None)
         self.ns_ldapprofile = NSLDAPProfile(None)
+        self.ns_ldapprofile.nameservice = NameServiceInfo(None)
+        self.ns_ldapprofile.nameservice.dns = False
         self.ns_ldapproxy = NSLDAPProxyBindInfo(None)
         self.ns_nisip = NSNISIP(None)
+        self.ns_nisip.nameservice = NameServiceInfo(None)
+        self.ns_nisip.nameservice.dns = False
 
     def tearDown(self):
+        NameServiceInfo.__init__ = self.NameServiceInfo__init__ 
         NSDomain.__init__ = self.NSDomain__init__
         NSDNSServer.__init__ = self.NSDNSServer__init__
         NSDNSSearch.__init__ = self.NSDNSSEARCH__init__
@@ -105,6 +112,8 @@
         self.ns_ldapprofile.ldap_profile = MockField('prof ile')
         self.assertRaises(UIMessage, self.ns_ldapprofile.validate)
 
+        self.dns = False
+        self.ns_ldapproxy.ldap_pb_dn = MockField('distinguishedname')
         self.ns_ldapproxy.ldap_pb_dn = MockField('distinguishedname')
         self.ns_ldapproxy.ldap_pb_psw = MockField('password')
         self.assertEqual(self.ns_ldapproxy.validate(), None)
--- a/usr/src/cmd/text-install/summary.py	Thu Jul 14 09:36:37 2011 -0700
+++ b/usr/src/cmd/text-install/summary.py	Thu Jul 14 11:33:34 2011 -0600
@@ -166,35 +166,41 @@
         if not self.sysconfig.nameservice:
             return
         nameservice = self.sysconfig.nameservice
-        if nameservice.nameservice and nameservice.domain:
+        if not nameservice.dns and not nameservice.nameservice:
+            return
+        if nameservice.domain:
             ns_summary.append(_("Domain: %s") % nameservice.domain)
-        ns_idx = NameService.CHOICE_LIST.index(nameservice.nameservice)
-        ns_summary.append(_("Name service: %s") %
-                NameService.USER_CHOICE_LIST[ns_idx])
-        if nameservice.nameservice == 'DNS':
+        # fetch localized name for name service
+        if nameservice.dns:
+            ns_summary.append(_("Name service: %s") %
+                              NameService.USER_CHOICE_DNS)
             # strip empty list entries
             dnslist = [ln for ln in nameservice.dns_server if ln]
             ns_summary.append(_("DNS servers: ") + " ".join(dnslist))
             dnslist = [ln for ln in nameservice.dns_search if ln]
-            ns_summary.append(_("Domain list: ") + " ".join(dnslist))
-        elif nameservice.nameservice == 'LDAP':
-            ns_summary.append(_("LDAP profile: ") +
-                                   nameservice.ldap_profile)
-            ns_summary.append(_("LDAP server's IP: ") +
-                                   nameservice.ldap_ip)
+            ns_summary.append(_("DNS Domain search list: ") +
+                              " ".join(dnslist))
+        if nameservice.nameservice == 'LDAP':
+            ns_idx = NameService.CHOICE_LIST.index(nameservice.nameservice)
+            ns_summary.append(_("Name service: %s") %
+                              NameService.USER_CHOICE_LIST[ns_idx])
+            ns_summary.append(_("LDAP profile: ") + nameservice.ldap_profile)
+            ns_summary.append(_("LDAP server's IP: ") + nameservice.ldap_ip)
+            ns_summary.append(_("LDAP search base: ") + 
+                              nameservice.ldap_search_base)
             if nameservice.ldap_proxy_bind == \
                     NameServiceInfo.LDAP_CHOICE_PROXY_BIND:
-                ns_summary.append(_(
-                                    "LDAP proxy bind distinguished name: ")
-                                    + nameservice.ldap_pb_dn)
-                ns_summary.append(_("LDAP proxy bind password: ") +
-                                       nameservice.ldap_pb_psw)
+                ns_summary.append(_("LDAP proxy bind distinguished name: ") +
+                                  nameservice.ldap_pb_dn)
+                ns_summary.append(_("LDAP proxy bind password: [concealed]"))
         elif nameservice.nameservice == 'NIS':
+            ns_idx = NameService.CHOICE_LIST.index(nameservice.nameservice)
+            ns_summary.append(_("Name service: %s") %
+                              NameService.USER_CHOICE_LIST[ns_idx])
             if nameservice.nis_auto == NameServiceInfo.NIS_CHOICE_AUTO:
                 ns_summary.append(_("NIS server: broadcast"))
             elif nameservice.nis_ip:
-                ns_summary.append(_("NIS server's IP: ") +
-                                       nameservice.nis_ip)
+                ns_summary.append(_("NIS server's IP: ") + nameservice.nis_ip)
 
     def get_users(self):
         '''Build a summary of the user information, and return it as a list