7032012 Make interactive system configuration scenario zone aware
authorJan Damborsky <dambi@opensolaris.org>
Fri, 27 May 2011 12:13:10 +0200
changeset 1155 4eb6bb7bb4a0
parent 1154 8cb36a37e75d
child 1156 a4d11fe1d64f
7032012 Make interactive system configuration scenario zone aware 7042110 Relocate /usr/bin/sysconfig to /usr/sbin/sysconfig to comply with PSARC/2011/128
usr/src/cmd/system-config/Makefile
usr/src/cmd/system-config/__init__.py
usr/src/cmd/system-config/network_type.py
usr/src/cmd/system-config/profile/__init__.py
usr/src/cmd/system-config/profile/network_info.py
usr/src/cmd/system-config/profile/system_info.py
usr/src/cmd/system-config/profile/test/test_system_info.py
usr/src/cmd/system-config/summary.py
usr/src/cmd/system-config/svc/svc-system-config
usr/src/cmd/system-config/test/test_summary.py
usr/src/cmd/system-config/test/test_sysconfig.py
usr/src/cmd/system-config/welcome.py
usr/src/pkg/manifests/system-install-configuration.mf
--- a/usr/src/cmd/system-config/Makefile	Fri May 27 09:34:25 2011 +0100
+++ b/usr/src/cmd/system-config/Makefile	Fri May 27 12:13:10 2011 +0200
@@ -46,7 +46,7 @@
 
 PYCMODULES=	$(PYMODULES:%.py=%.pyc)
 
-ROOTPROGS=	$(PROGS:%=$(ROOTUSRBIN)/%)
+ROOTPROGS=	$(PROGS:%=$(ROOTUSRSBIN)/%)
 
 ROOTPYMODULES=	$(PYMODULES:%=$(ROOTPYTHONVENDORSCI)/%)
 
--- a/usr/src/cmd/system-config/__init__.py	Fri May 27 09:34:25 2011 +0100
+++ b/usr/src/cmd/system-config/__init__.py	Fri May 27 12:13:10 2011 +0200
@@ -27,12 +27,6 @@
 
 
 import gettext
-
-_ = gettext.translation("sysconfig", "/usr/share/locale",
-                        fallback=True).ugettext
-SCI_HELP = "/usr/share/sysconfig/help"
-
-
 import atexit
 import curses
 import gettext
@@ -43,8 +37,67 @@
 import signal
 import sys
 
+from solaris_install.data_object import DataObject
 from solaris_install import engine
 from solaris_install.engine import InstallEngine, RollbackError
+
+_ = gettext.translation("sysconfig", "/usr/share/locale",
+                        fallback=True).ugettext
+SCI_HELP = "/usr/share/sysconfig/help"
+
+# system configuration groups
+# hostname
+SC_GROUP_IDENTITY = 'identity'
+# networking
+SC_GROUP_NETWORK = "network"
+# naming services
+SC_GROUP_NS = 'naming_services'
+# keyboard layout
+SC_GROUP_KBD = 'kbd_layout'
+# date and time
+SC_GROUP_DATETIME = 'date_time'
+# timezone and locale
+SC_GROUP_LOCATION = 'location'
+# user and root account
+SC_GROUP_USERS = 'users'
+# pseudo-group - includes all available groups
+SC_GROUP_SYSTEM = 'system'
+
+# list of configuration groups
+SC_ALL_GROUPS = [SC_GROUP_IDENTITY, SC_GROUP_NETWORK, SC_GROUP_NS,
+                 SC_GROUP_KBD, SC_GROUP_LOCATION, SC_GROUP_DATETIME,
+                 SC_GROUP_USERS]
+
+# all valid configuration groups including 'system' pseudo-group
+SC_VALID_GROUPS = SC_ALL_GROUPS + [SC_GROUP_SYSTEM]
+
+
+def get_sc_options_from_doc():
+    '''Obtains list of sysconfig CLI options from Data Object Cache'''
+    doc = InstallEngine.get_instance().doc.persistent
+    sc_options = doc.get_first_child(name=SC_OPTIONS_LABEL)
+
+    if sc_options is not None:
+        return sc_options.options
+    else:
+        return None
+
+
+def configure_group(group=None):
+    '''Returns True if specified group is to be configured,
+    otherwise returns False'''
+
+    sc_options = get_sc_options_from_doc()
+
+    # if list of groups can't be obtained, assume everything
+    # is to be configured
+    if sc_options is None:
+        return True
+    elif group in sc_options.grouping:
+        return True
+    else:
+        return False
+
 from solaris_install.logger import FileHandler, INSTALL_LOGGER_NAME
 from solaris_install.sysconfig.date_time import DateTimeScreen
 from solaris_install.sysconfig.network_nic_configure import NICConfigure
@@ -67,6 +120,9 @@
 from terminalui.main_window import MainWindow
 from terminalui.screen_list import ScreenList
 
+VOLATILE_PATH = "/system/volatile/profile"
+SC_PROFILE = "profile_sc_manifest.xml"
+DEFAULT_SC_LOCATION = os.path.join(VOLATILE_PATH, SC_PROFILE)
 
 DEFAULT_LOG_LOCATION = "/var/tmp/install/sysconfig.log"
 DEFAULT_LOG_LEVEL = "info"
@@ -75,19 +131,42 @@
 LOGGER = None
 XSLT_FILE = os.environ.get('SC_XSLT',
                            '/usr/share/sysconfig/xslt/doc2sc_profile.xslt')
-SC_FILE = os.environ.get('SC_FILE',
-                         '/system/volatile/profile/profile_sc_manifest.xml')
+SC_FILE = DEFAULT_SC_LOCATION
+GENERATE_SC_PROFILE_CHKPOINT = 'generate-sc-profile'
+
+# sysconfig subcommands
+CREATE_PROFILE = "create-profile"
+
+# DOC label for SysConfig options 
+SC_OPTIONS_LABEL = "sc_options"
+
 
-GENERATE_SC_PROFILE_CHKPOINT='generate-sc-profile'
+class SysConfigOptions(DataObject):
+    '''System Configuration options'''
+    
+    def __init__(self, options=None):
+        super(SysConfigOptions, self).__init__(SC_OPTIONS_LABEL)
+        self.options = options
+    
+    def to_xml(self):
+        return None
+    
+    @classmethod
+    def can_handle(cls, element):
+        return False
+    
+    @classmethod
+    def from_xml(cls, element):
+        return None
 
 
 # Public functions for consumers of sysconfig
 
 def get_all_screens(main_win):
-    '''Initializes a full set of screens'''
-    
+    '''Initializes a full set of configuration screens'''
+
     result = []
-    result.append(NetworkTypeScreen(main_win))
+    result.append(NetworkTypeScreen(main_win, True))
     result.append(NICSelect(main_win))
     result.append(NICConfigure(main_win))
     result.append(TimeZone(main_win, screen=TimeZone.REGIONS))
@@ -95,7 +174,40 @@
     result.append(TimeZone(main_win))
     result.append(DateTimeScreen(main_win))
     result.append(UserScreen(main_win))
+      
+    return result
+
+
+def get_screens_from_groups(main_win):
+    '''Initializes subset of configuration screens matching list of specified
+    configuration groups'''
     
+    result = []
+
+    # hostname
+    if configure_group(SC_GROUP_IDENTITY):
+        result.append(NetworkTypeScreen(main_win,
+                                        configure_group(SC_GROUP_NETWORK)))
+
+    # network
+    if configure_group(SC_GROUP_NETWORK):
+        result.append(NICSelect(main_win))
+        result.append(NICConfigure(main_win))
+
+    # timezone
+    if configure_group(SC_GROUP_LOCATION):
+        result.append(TimeZone(main_win, screen=TimeZone.REGIONS))
+        result.append(TimeZone(main_win, screen=TimeZone.LOCATIONS))
+        result.append(TimeZone(main_win))
+
+    # date and time
+    if configure_group(SC_GROUP_DATETIME):
+        result.append(DateTimeScreen(main_win))
+
+    # initial user
+    if configure_group(SC_GROUP_USERS):
+        result.append(UserScreen(main_win))
+
     return result
 
 
@@ -104,7 +216,7 @@
     Also adds config_profile to InstallEngine.doc.persistent'''
     eng = InstallEngine.get_instance()
     
-    sc_kwargs = {'xslt_file' : xslt}
+    sc_kwargs = {'xslt_file': xslt}
     sc_args = [sc_profile]
     eng.register_checkpoint(GENERATE_SC_PROFILE_CHKPOINT,
                             "solaris_install/manifest/writer",
@@ -113,39 +225,20 @@
     eng.doc.persistent.insert_children([ConfigProfile()])
 
 
-# Private functions for use by /usr/bin/sysconfig
+def parse_create_profile_args(parser, args):
+    '''Parses command line options for 'create-profile' sysconfig subcommand.
+    '''
+    (options, sub_cmd) = parser.parse_args(args)
 
-def _parse_options(arguments):
-    usage = "usage: %prog [-l FILE] [-v LEVEL] [-n] [-b]"
-    parser = OptionParser(usage=usage)
-    
-    parser.add_option("-l", "--log-location", dest="logname",
-                      help=_("Set log location to FILE (default: %default)"),
-                      metavar="FILE", default=DEFAULT_LOG_LOCATION)
-    parser.add_option("-v", "--log-level", dest="log_level",
-                      default=DEFAULT_LOG_LEVEL,
-                      help=_("Set log verbosity to LEVEL. In order of "
-                             "increasing verbosity, valid values are 'error' "
-                             "'warn' 'info' 'debug' or 'input'\n[default:"
-                             " %default]"),
-                      choices=["error", "warn", "info", "debug", "input"],
-                      metavar="LEVEL")
-    parser.add_option("-b", "--no-color", action="store_true", dest="force_bw",
-                      default=False, help=_("Force the tool to run in "
-                      "black and white. This may be useful on some SPARC "
-                      "machines with unsupported frame buffers\n"))
-    parser.add_option("-n", action="store_true",
-                      dest="dry_run", default=False,
-                      help=_("Runs the tool, but does not apply the "
-                             "configuration to the system.\n"))
-    
-    options, args = parser.parse_args(arguments)
-    
-    if args:
-        parser.error("Unexpected positional argument(s): %s" % args)
-    
+    # List of configuration groups - entries are separated by commas
+    options.grouping = options.grouping.split(',')
+    # If the user specified 'system' in a list of groups, configure all groups.
+    if SC_GROUP_SYSTEM in options.grouping:
+        options.grouping = SC_ALL_GROUPS
+
+    # Run Install Engine in debug mode
     options.debug = (options.log_level.lower() in ['debug', 'input'])
-    
+
     log_level = options.log_level.upper()
     if hasattr(logging, log_level):
         options.log_level = getattr(logging, log_level.upper())
@@ -153,8 +246,97 @@
         options.log_level = LOG_LEVEL_INPUT
     else:
         raise IOError(2, "Invalid --log-level parameter", log_level.lower())
-    
-    return options
+
+    return (options, sub_cmd)
+
+
+def do_create_profile(options):
+    '''Run System Configuration Interactive Tool in order to create
+    System Configuration profile'''
+    try:
+        _prepare_engine(options)
+
+        # insert sysconfig CLI options into DOC
+        doc_options = SysConfigOptions(options)
+        doc = InstallEngine.get_instance().doc.persistent
+        doc.insert_children(doc_options)
+
+        _show_screens(options)
+        _exit(options.logname, errcode=0)
+    except SystemExit:
+        raise
+    except:
+        if LOGGER is None:
+            # Error occurred before logging is setup; no place to
+            # dump the traceback
+            raise
+        LOGGER.exception(_("An unhandled exception occurred."))
+        exc_type, exc_value = sys.exc_info()[:2]
+
+        try:
+            doc = InstallEngine.get_instance().doc.persistent
+            sc_prof = doc.get_first_child(name="sysconfig")
+            LOGGER.error("Sysconfig profile:\n%s", sc_prof)
+        except:
+            # Ignore any errors to avoid masking the original exception
+            pass
+
+        print _("An unhandled exception occurred.")
+        if exc_value:
+            print '\t%s: "%s"' % (exc_type.__name__, exc_value)
+        else:
+            print "\t%s" % exc_type.__name__
+        print _("Full traceback data is in the log")
+        _exit(options.logname, errcode=1)
+
+# Private functions for use by /usr/sbin/sysconfig
+
+
+def _parse_options(arguments):
+    ''' Parses sysconfig subcommands'''
+
+    usage = "\t%prog create-profile [-g grouping, grouping,...] " + \
+            "[-o output_file] [-l logfile] [-v verbosity] [-b]"
+    parser = OptionParser(usage=usage)
+
+    # This allows parsing of different subcommand options. It stops
+    # parsing after the subcommand is populated.
+    parser.disable_interspersed_args()
+    (options, sub_cmd) = parser.parse_args(arguments)
+    parser.enable_interspersed_args()
+
+    if not sub_cmd:
+        parser.error("Subcommand not specified")
+    if sub_cmd[0] == CREATE_PROFILE:
+        parser.add_option("-g", dest="grouping",
+                          help=_("Groups to configure"),
+                          default=SC_GROUP_SYSTEM)
+        parser.add_option("-o", dest="profile", metavar="FILE",
+                          help=_("Saves created system configuration profile "
+                          "into FILE.\t\t[default: %default]"),
+                          default=DEFAULT_SC_LOCATION)
+        parser.add_option("-l", "--log-location", dest="logname",
+                          help=_("Set log location to FILE "
+                          "(default: %default)"),
+                          metavar="FILE", default=DEFAULT_LOG_LOCATION)
+        parser.add_option("-v", "--log-level", dest="log_level",
+                          default=DEFAULT_LOG_LEVEL,
+                          help=_("Set log verbosity to LEVEL. In order of "
+                          "increasing verbosity, valid values are 'error' "
+                          "'warn' 'info' 'debug' or 'input'\n[default:"
+                          " %default]"),
+                          choices=["error", "warn", "info", "debug", "input"],
+                          metavar="LEVEL")
+        parser.add_option("-b", "--no-color", action="store_true",
+                          dest="force_bw", default=False,
+                          help=_("Force the tool to run in "
+                          "black and white. This may be useful on some SPARC "
+                          "machines with unsupported frame buffers\n"))
+        (options, sub_cmd) = parse_create_profile_args(parser, arguments)
+    else:
+        parser.error("Invalid subcommand")
+
+    return (options, sub_cmd)
 
 
 def _exit(logname, errcode=0):
@@ -172,7 +354,7 @@
 def _make_screen_list(main_win):
     screens = []
     screens.append(WelcomeScreen(main_win))
-    screens.extend(get_all_screens(main_win))
+    screens.extend(get_screens_from_groups(main_win))
     screens.append(SummaryScreen(main_win))
     
     return screens
@@ -216,8 +398,7 @@
 
 def _prepare_engine(options):
     '''Initialize the InstallEngine'''
-    eng = InstallEngine(loglevel=options.log_level, debug=options.debug)
-    
+    InstallEngine(loglevel=options.log_level, debug=options.debug)
     
     logger = logging.getLogger(INSTALL_LOGGER_NAME)
     logger.addHandler(FileHandler(options.logname, mode='w'))
@@ -231,10 +412,11 @@
     
     terminalui.init_logging(INSTALL_LOGGER_NAME)
     
-    register_checkpoint()
+    register_checkpoint(sc_profile=options.profile)
 
 
 def _init_locale():
+    '''Initializes the locale'''
     locale.setlocale(locale.LC_ALL, "")
     gettext.install("sysconfig", "/usr/share/locale", unicode=True)
     set_wrap_on_whitespace(_("DONT_TRANSLATE_BUT_REPLACE_msgstr_WITH_True_"
@@ -247,44 +429,15 @@
 
 
 def main():
+    '''Main Function'''
     _init_locale()
-    
-    options = _parse_options(sys.argv[1:])
-    
-    if os.getuid() != 0:
-        sys.exit(_("The System Configuration tool must be run "
-                   "with root privileges"))
-    
-    try:
-        _prepare_engine(options)
-        _show_screens(options)
-        _exit(options.logname, errcode=0)
-    except SystemExit:
-        raise
-    except:
-        if LOGGER is None:
-            # Error occurred before logging is setup; no place to
-            # dump the traceback
-            raise
-        LOGGER.exception(_("An unhandled exception occurred."))
-        exc_type, exc_value = sys.exc_info()[:2]
-        
-        try:
-            doc = InstallEngine.get_instance().doc.persistent
-            sc_prof = doc.get_first_child(name="sysconfig")
-            LOGGER.error("Sysconfig profile:\n%s", sc_prof)
-        except:
-            # Ignore any errors to avoid masking the original exception
-            pass
-        
-        print _("An unhandled exception occurred.")
-        if exc_value:
-            print '\t%s: "%s"' % (exc_type.__name__, exc_value)
-        else:
-            print "\t%s" % exc_type.__name__
-        print _("Full traceback data is in the log")
-        _exit(options.logname, errcode=1)
+
+    (options, sub_cmd) = _parse_options(sys.argv[1:])
 
+    if sub_cmd[0] == CREATE_PROFILE:
+        do_create_profile(options)
+
+    sys.exit(SU_OK)
 
 if __name__ == '__main__':
     main()
--- a/usr/src/cmd/system-config/network_type.py	Fri May 27 09:34:25 2011 +0100
+++ b/usr/src/cmd/system-config/network_type.py	Fri May 27 12:13:10 2011 +0200
@@ -74,7 +74,7 @@
     
     HELP_DATA = (SCI_HELP + "/%s/network.txt", _("Network"))
     
-    def __init__(self, main_win):
+    def __init__(self, main_win, configure_network=False):
         global LOGGER
         if LOGGER is None:
             LOGGER = logging.getLogger(INSTALL_LOGGER_NAME + ".sysconfig")
@@ -95,6 +95,7 @@
         self.have_nic = True
         if len(self.ether_nics) == 0:
             self.have_nic = False
+        self.configure_network = configure_network
     
     def _show(self):
         '''Create an EditField for entering hostname, and list items
@@ -128,51 +129,53 @@
                                   validate=hostname_is_valid,
                                   error_win=self.main_win.error_line)
         self.hostname.item_key = None
-        
-        y_loc += 3
+
+        # Display network configuration part of screen only if applicable.
+        if self.configure_network:
+            y_loc += 3
         
-        if not self.have_nic:
-            self.center_win.add_paragraph(NetworkTypeScreen.NO_NICS_FOUND,
-                                          y_loc, 1)
-            self.main_win.do_update()
-            activate = self.net_type_dict.get(self.nic_info.type,
-                                              self.hostname)
-            self.center_win.activate_object(activate)
-            return
+            if not self.have_nic:
+                self.center_win.add_paragraph(NetworkTypeScreen.NO_NICS_FOUND,
+                                              y_loc, 1)
+                self.main_win.do_update()
+                activate = self.net_type_dict.get(self.nic_info.type,
+                                                  self.hostname)
+                self.center_win.activate_object(activate)
+                return
         
-        y_loc += self.center_win.add_paragraph(NetworkTypeScreen.NET_TYPE_TEXT,
-                                               y_loc)
+            y_loc += self.center_win.add_paragraph(
+                     NetworkTypeScreen.NET_TYPE_TEXT, y_loc)
         
-        y_loc += 1
-        item_area = WindowArea(1, NetworkTypeScreen.ITEM_MAX_WIDTH, y_loc,
-                               NetworkTypeScreen.ITEM_OFFSET)
-        self.automatic = ListItem(item_area, window=self.center_win,
-                                  text=NetworkTypeScreen.AUTO_TEXT)
-        self.automatic.item_key = NetworkInfo.AUTOMATIC
-        self.net_type_dict[self.automatic.item_key] = self.automatic
-        self.center_win.add_text(NetworkTypeScreen.AUTO_DETAIL, y_loc,
-                                 NetworkTypeScreen.ITEM_DESC_OFFSET,
-                                 self.menu_item_desc_max)
+            y_loc += 1
+            item_area = WindowArea(1, NetworkTypeScreen.ITEM_MAX_WIDTH, y_loc,
+                                   NetworkTypeScreen.ITEM_OFFSET)
+            self.automatic = ListItem(item_area, window=self.center_win,
+                                      text=NetworkTypeScreen.AUTO_TEXT)
+            self.automatic.item_key = NetworkInfo.AUTOMATIC
+            self.net_type_dict[self.automatic.item_key] = self.automatic
+            self.center_win.add_text(NetworkTypeScreen.AUTO_DETAIL, y_loc,
+                                     NetworkTypeScreen.ITEM_DESC_OFFSET,
+                                     self.menu_item_desc_max)
         
-        y_loc += 2
-        item_area.y_loc = y_loc
-        self.manual = ListItem(item_area, window=self.center_win,
-                               text=NetworkTypeScreen.MANUAL_TEXT)
-        self.manual.item_key = NetworkInfo.MANUAL
-        self.net_type_dict[self.manual.item_key] = self.manual
-        self.center_win.add_text(NetworkTypeScreen.MANUAL_DETAIL, y_loc,
-                                 NetworkTypeScreen.ITEM_DESC_OFFSET,
-                                 self.menu_item_desc_max)
-        
-        y_loc += 2
-        item_area.y_loc = y_loc
-        self.none_option = ListItem(item_area, window=self.center_win,
-                                    text=NetworkTypeScreen.NONE_TEXT)
-        self.none_option.item_key = NetworkInfo.NONE
-        self.net_type_dict[self.none_option.item_key] = self.none_option
-        self.center_win.add_text(NetworkTypeScreen.NONE_DETAIL, y_loc,
-                                 NetworkTypeScreen.ITEM_DESC_OFFSET,
-                                 self.menu_item_desc_max)
+            y_loc += 2
+            item_area.y_loc = y_loc
+            self.manual = ListItem(item_area, window=self.center_win,
+                                   text=NetworkTypeScreen.MANUAL_TEXT)
+            self.manual.item_key = NetworkInfo.MANUAL
+            self.net_type_dict[self.manual.item_key] = self.manual
+            self.center_win.add_text(NetworkTypeScreen.MANUAL_DETAIL, y_loc,
+                                     NetworkTypeScreen.ITEM_DESC_OFFSET,
+                                     self.menu_item_desc_max)
+
+            y_loc += 2
+            item_area.y_loc = y_loc
+            self.none_option = ListItem(item_area, window=self.center_win,
+                                        text=NetworkTypeScreen.NONE_TEXT)
+            self.none_option.item_key = NetworkInfo.NONE
+            self.net_type_dict[self.none_option.item_key] = self.none_option
+            self.center_win.add_text(NetworkTypeScreen.NONE_DETAIL, y_loc,
+                                     NetworkTypeScreen.ITEM_DESC_OFFSET,
+                                     self.menu_item_desc_max)
         
         self.main_win.do_update()
         activate = self.net_type_dict.get(self.nic_info.type,
@@ -181,10 +184,10 @@
     
     def on_change_screen(self):
         '''Save hostname and selected network type on change screen'''
-        if self.have_nic:
+        if self.configure_network and self.have_nic:
             self.nic_info.type = self.center_win.get_active_object().item_key
         else:
-            self.nic_info.type = NetworkInfo.NONE
+            self.nic_info.type = None
         LOGGER.info("Configuring NIC as: %s", self.nic_info.type)
         self.sys_info.hostname = self.hostname.get_text()
     
@@ -198,7 +201,7 @@
             raise UIMessage(_("A Hostname is required."))
         if len(hostname_text) < 2:
             raise UIMessage(_("A Hostname must be at least two characters."))
-        if self.have_nic:
+        if self.configure_network and self.have_nic:
             item_key = self.center_win.get_active_object().item_key
             if item_key not in self.net_type_dict:
                 raise UIMessage(_("Select the wired network configuration: "
--- a/usr/src/cmd/system-config/profile/__init__.py	Fri May 27 09:34:25 2011 +0100
+++ b/usr/src/cmd/system-config/profile/__init__.py	Fri May 27 12:13:10 2011 +0200
@@ -33,6 +33,7 @@
 NETWORK_LABEL = "nic"
 SYSTEM_LABEL = 'system_info'
 
+
 def from_engine():
     '''Convenience function for getting the ConfigProfile from
     the engine's DOC instance.
@@ -149,7 +150,9 @@
         
         if self.system:
             element.extend(self.system.to_xml())
-        if self.nic:
+
+        # generate network configuration only if network group was configured
+        if self.nic and self.nic.type is not None:
             element.extend(self.nic.to_xml())
         
         return element
@@ -161,6 +164,7 @@
     @classmethod
     def can_handle(cls, xml_node):
         return False
+
     
 class SMFConfig(DataObject):
     '''Represent a single SMF service. Stores SMFInstances
@@ -183,6 +187,7 @@
     @classmethod
     def can_handle(cls, xml_node):
         return False
+
     
 class SMFInstance(DataObject):
     '''Represent an instance of SMF service. Stores SMFPropertyGroups'''
@@ -193,8 +198,8 @@
    
     def to_xml(self):
         enabled = 'true' if self.enabled else 'false'
-        element = etree.Element('instance', enabled = enabled,
-                                name = self.name)
+        element = etree.Element('instance', enabled=enabled,
+                                name=self.name)
         return element
     
     @classmethod
@@ -205,6 +210,7 @@
     def can_handle(cls, xml_node):
         return False
 
+
 class SMFPropertyGroup(DataObject):
     '''Stores SMFProperties'''
     
@@ -323,7 +329,7 @@
             if not isinstance(val, basestring):
                 raise ValueError("'%s' must be a string or unicode object" %
                                  val)
-            elem_vals.append(XMLElement('value_node', {'value' : val}))
+            elem_vals.append(XMLElement('value_node', {'value': val}))
         
         elem_type.delete_children()
         elem_type.insert_children(elem_vals)
@@ -331,9 +337,9 @@
     def to_xml(self):
         elem_kwargs = {}
         # map attributes of SMFProperty class to xml attributes in smf profile
-        obj_attr2xml_attr = {'proptype':'type',
-                             'propname':'name',
-                             'propval':'value'}
+        obj_attr2xml_attr = {'proptype': 'type',
+                             'propname': 'name',
+                             'propval': 'value'}
 
         for attr in ['proptype', 'propname', 'propval']:
             val = getattr(self, attr)
@@ -377,4 +383,3 @@
     '''
     return create_prop_group("other_sc_params", timezone=timezone,
                              hostname=hostname)
-
--- a/usr/src/cmd/system-config/profile/network_info.py	Fri May 27 09:34:25 2011 +0100
+++ b/usr/src/cmd/system-config/profile/network_info.py	Fri May 27 12:13:10 2011 +0200
@@ -28,8 +28,7 @@
 '''
 
 import logging
-from subprocess import Popen, PIPE
-
+from solaris_install import Popen, CalledProcessError
 from solaris_install.data_object import DataObject
 from solaris_install.logger import INSTALL_LOGGER_NAME
 from solaris_install.sysconfig.profile.ip_address import IPAddress
@@ -61,27 +60,62 @@
     
     @staticmethod
     def find_links():
-        '''Use dladm show-link to find the physical links
-        on the system
-        
+        '''Use dladm show-link to find available network interfaces (NICs).
+        Filter out NICs with 'allow-address' mandated from global zone
+        (this type of NIC can be configured for non-global zone with exclusive
+        IP stack), since those kind of NICs are controlled from global zone
+        and can't be configured within non-global zone.
         '''
-        
+
         if NetworkInfo.ETHER_NICS is not None:
             return NetworkInfo.ETHER_NICS
         
         argslist = ['/usr/sbin/dladm', 'show-link', '-o', 'link', '-p']
         
         try:
-            (nic_list, dladm_err) = Popen(argslist, stdout=PIPE,
-                                          stderr=PIPE).communicate()
-        except OSError, err:
-            LOGGER().warn("OSError occurred: %s", err)
+            dladm_popen = Popen.check_call(argslist, stdout=Popen.STORE,
+                                           stderr=Popen.STORE, logger=LOGGER())
+        except CalledProcessError as error:
+            LOGGER().warn("'dladm show-link -o link -p' "
+                          "failed with following error: %s", error)
+
             return []
-        if dladm_err:
-            LOGGER().warn("Error occurred during call to dladm: %s", dladm_err)
+
+        nic_list = dladm_popen.stdout.strip()
+
+        #
         # pylint: disable-msg=E1103
         # nic_list is a string
-        NetworkInfo.ETHER_NICS = nic_list.splitlines()
+        # Start with empty list of NICs and add those which are eligible
+        # for configuration.
+        #
+        NetworkInfo.ETHER_NICS = []
+        all_nics = nic_list.splitlines()
+
+        for nic in all_nics:
+            argslist = ['/usr/sbin/dladm', 'show-linkprop', '-c', '-p',
+                        'allowed-ips', '-o', 'value', nic]
+
+            try:
+                dladm_popen = Popen.check_call(argslist, stdout=Popen.STORE,
+                                               stderr=Popen.STORE,
+                                               logger=LOGGER())
+            except CalledProcessError as error:
+                LOGGER().warn("'dladm show-linkprop -c -p allowed-ips -o "
+                              "value' failed with following error: %s", error)
+                continue
+
+            allowed_ips = dladm_popen.stdout.strip()
+
+            #
+            # Add particular NIC to the list if 'allowed-ips' link property
+            # is not configured (is empty).
+            #
+            LOGGER().info("%s allowed-ips: <%s>" % (nic, allowed_ips))
+            if not allowed_ips:
+                NetworkInfo.ETHER_NICS.append(nic)
+
+        # sort the final list
         NetworkInfo.ETHER_NICS.sort()
         return NetworkInfo.ETHER_NICS
 
@@ -185,23 +219,21 @@
         '''
         argslist = ['/sbin/ifconfig', self.nic_name]
         try:
-            (ifconfig_out, ifconfig_err) = Popen(argslist, stdout=PIPE,
-                                                 stderr=PIPE).communicate()
-        except OSError, err:
-            LOGGER().warn("Failed to call ifconfig: %s", err)
+            ifconfig_popen = Popen.check_call(argslist, stdout=Popen.STORE,
+                                              stderr=Popen.STORE,
+                                              logger=LOGGER())
+        except CalledProcessError as error:
+            LOGGER().warn("'ifconfig' failed with following error: %s", error)
             return None
-        if ifconfig_err:
-            LOGGER().warn("Error occurred during call to ifconfig: %s",
-                         ifconfig_err)
-            return None
+
         # pylint: disable-msg=E1103
         # ifconfig_out is a string
-        ifconfig_out = ifconfig_out.split()
+        ifconfig_out = ifconfig_popen.stdout.split()
         link_data = {}
         link_data['flags'] = ifconfig_out[1]
         ifconfig_out = ifconfig_out[2:]
         for i in range(len(ifconfig_out) / 2):
-            link_data[ifconfig_out[2*i]] = ifconfig_out[2*i+1]
+            link_data[ifconfig_out[2 * i]] = ifconfig_out[2 * i + 1]
         return link_data
     
     def _run_dhcpinfo(self, code):
@@ -212,7 +244,7 @@
         '''
         ifconfig_data = self.get_ifconfig_data()
         if not ifconfig_data or ifconfig_data['flags'].count("DHCP") == 0:
-            LOGGER().warn("This connection not using DHCP")
+            LOGGER().warn("This connection is not using DHCP")
             return None
         
         argslist = ['/sbin/dhcpinfo',
@@ -220,22 +252,20 @@
                     '-n', '1',
                     code]
         try:
-            (dhcpout, dhcperr) = Popen(argslist, stdout=PIPE,
-                                       stderr=PIPE).communicate()
-        except OSError, err:
-            LOGGER().warn("OSError ocurred during dhcpinfo call: %s", err)
+            dhcp_popen = Popen.check_call(argslist, stdout=Popen.STORE,
+                                          stderr=Popen.STORE, logger=LOGGER())
+        except CalledProcessError as error:
+            LOGGER().warn("'dhcpinfo -i %s -n 1' failed with following error:"
+                          " %s" % (self.nic_name, error))
             return None
-        
-        if dhcperr:
-            LOGGER().warn("Error ocurred during dhcpinfo call: %s", dhcperr)
-        
+            
         # pylint: disable-msg=E1103
         # dhcpout is a string
-        return dhcpout.rstrip("\n")
+        return dhcp_popen.stdout.rstrip("\n")
     
     def to_xml(self):
         data_objects = []
-        
+
         net_physical = SMFConfig("network/physical")
         data_objects.append(net_physical)
         
--- a/usr/src/cmd/system-config/profile/system_info.py	Fri May 27 09:34:25 2011 +0100
+++ b/usr/src/cmd/system-config/profile/system_info.py	Fri May 27 12:13:10 2011 +0200
@@ -76,7 +76,7 @@
     def __init__(self, hostname=None, tz_region=None,
                  tz_country=None, tz_timezone=None, time_offset=0,
                  keyboard=None, locale=None, actual_lang=None,
-                 terminal_type = None, users=None):
+                 terminal_type=None, users=None):
         data_object.DataObject.__init__(self, self.LABEL)
         
         if hostname is None:
@@ -179,7 +179,7 @@
         except IOError as err:
             status = err.errno
             LOGGER().warn("fcntl.ioctl() KIOCLAYOUT_FAILED: status=%s",
-                         status = err.errno)
+                         status=err.errno)
             kbd.close()
             return None
         
@@ -214,7 +214,6 @@
 
         return kbd_layout_name
 
-
     @staticmethod
     def determine_terminal_type():
         '''Determine default value for terminal type from type
@@ -306,7 +305,6 @@
 
         return term_type
 
-
     def determine_locale(self):
         '''Read in the language set during boot.'''
         # getdefaultlocale() returns a tuple such as ('en_US', 'UTF8')
@@ -364,10 +362,12 @@
         
         instance = SMFInstance("default")
         install_config.insert_children([instance])
-        other_sc_params = SMFPropertyGroup('other_sc_params')
-        instance.insert_children([other_sc_params])
+
+        if self.tz_timezone is not None:
+            other_sc_params = SMFPropertyGroup('other_sc_params')
+            instance.insert_children([other_sc_params])
         
-        other_sc_params.add_props(timezone=self.tz_timezone)
+            other_sc_params.add_props(timezone=self.tz_timezone)
         
         instance.insert_children(self.users)
 
@@ -432,4 +432,3 @@
     @classmethod
     def can_handle(cls, xml_node):
         return False
-
--- a/usr/src/cmd/system-config/profile/test/test_system_info.py	Fri May 27 09:34:25 2011 +0100
+++ b/usr/src/cmd/system-config/profile/test/test_system_info.py	Fri May 27 12:13:10 2011 +0200
@@ -52,7 +52,7 @@
   <service version="1" type="service" name="system/config">
     <instance enabled="true" name="default">
       <property_group type="application" name="other_sc_params">
-        <propval type="astring" name="timezone"/>
+        <propval type="astring" name="timezone" value="Europe/Prague"/>
       </property_group>
     </instance>
   </service>
@@ -78,6 +78,7 @@
 </root>
 '''
 
+
 class TestSysInfoToXML(unittest.TestCase):
     
     def test_to_xml(self):
@@ -85,7 +86,7 @@
         Only concerned with structure, so propvals are ignored.
         
         '''
-        sys = SystemInfo()
+        sys = SystemInfo(tz_timezone='Europe/Prague')
         xml = sys.to_xml()
         xml_root = etree.fromstring("<root/>")
         xml_root.extend(xml)
--- a/usr/src/cmd/system-config/summary.py	Fri May 27 09:34:25 2011 +0100
+++ b/usr/src/cmd/system-config/summary.py	Fri May 27 12:13:10 2011 +0200
@@ -31,7 +31,10 @@
 
 from solaris_install.logger import INSTALL_LOGGER_NAME
 from solaris_install.engine import InstallEngine
-from solaris_install.sysconfig import _, SCI_HELP
+from solaris_install.sysconfig import _, SCI_HELP, configure_group, \
+                                      SC_GROUP_IDENTITY, SC_GROUP_NETWORK, \
+                                      SC_GROUP_KBD, SC_GROUP_LOCATION, \
+                                      SC_GROUP_USERS
 import solaris_install.sysconfig.profile
 from solaris_install.sysconfig.profile.network_info import NetworkInfo
 from solaris_install.sysconfig.profile.user_info import UserInfo
@@ -88,7 +91,7 @@
         max_chars = self.win_size_x - SummaryScreen.INDENT - 1
         summary_text = convert_paragraph(summary_text, max_chars)
         area = WindowArea(x_loc=0, y_loc=y_loc,
-                          scrollable_lines=(len(summary_text)+1))
+                          scrollable_lines=(len(summary_text) + 1))
         area.lines = self.win_size_y - y_loc
         area.columns = self.win_size_x
         scroll_region = ScrollWindow(area, window=self.center_win)
@@ -114,28 +117,43 @@
         else:
             summary_text = []
         
-            summary_text.append(self.get_tz_summary())
-            summary_text.append("")
-            summary_text.append(_("Language: *The following can be changed "
-                                  "when logging in."))
-            if self.sysconfig.system.locale is None:
-                self.sysconfig.system.determine_locale()
-            summary_text.append(_("  Default language: %s") %
-                                self.sysconfig.system.actual_lang)
-            summary_text.append("")
-            summary_text.append(_("Keyboard layout: *The following can be "
-                                  "changed when logging in."))
-            summary_text.append(_("  Default keyboard layout: %s") %
-                                self.sysconfig.system.keyboard)
-            summary_text.append("")
+            # display summary only for configured areas
+            # locale and timezone belong to SC_GROUP_LOCATION group
+            if configure_group(SC_GROUP_LOCATION):
+                summary_text.append(self.get_tz_summary())
+
+                summary_text.append("")
+                summary_text.append(_("Language: *The following can be changed"
+                                      " when logging in."))
+                if self.sysconfig.system.locale is None:
+                    self.sysconfig.system.determine_locale()
+                summary_text.append(_("  Default language: %s") %
+                                    self.sysconfig.system.actual_lang)
+
+            # keyboard layout belongs to SC_GROUP_KBD group
+            if configure_group(SC_GROUP_KBD):
+                summary_text.append("")
+                summary_text.append(_("Keyboard layout: *The following can be "
+                                      "changed when logging in."))
+                summary_text.append(_("  Default keyboard layout: %s") %
+                                    self.sysconfig.system.keyboard)
+                summary_text.append("")
+
             summary_text.append(_("Terminal type: %s") %
                                 self.sysconfig.system.terminal_type)
-            summary_text.append("")
-            summary_text.append(_("Users:"))
-            summary_text.extend(self.get_users())
-            summary_text.append("")
-            summary_text.append(_("Network:"))
-            summary_text.extend(self.get_networks())
+
+            # user/root accounts belong to SC_GROUP_USERS group
+            if configure_group(SC_GROUP_USERS):
+                summary_text.append("")
+                summary_text.append(_("Users:"))
+                summary_text.extend(self.get_users())
+
+            # network belongs to SC_GROUP_IDENTITY and SC_GROUP_NETWORK groups
+            if configure_group(SC_GROUP_NETWORK) or \
+               configure_group(SC_GROUP_IDENTITY):
+                summary_text.append("")
+                summary_text.append(_("Network:"))
+                summary_text.extend(self.get_networks())
         
             return "\n".join(summary_text)
 
@@ -145,10 +163,16 @@
         
         '''
         network_summary = []
-        network_summary.append(_("  Computer name: %s") %
-                               self.sysconfig.system.hostname)
-        nic = self.sysconfig.nic
-        
+
+        # hostname belongs to 'identity' group
+        if configure_group(SC_GROUP_IDENTITY):
+            network_summary.append(_("  Computer name: %s") %
+                                   self.sysconfig.system.hostname)
+
+        if not configure_group(SC_GROUP_NETWORK):
+            return network_summary
+
+        nic = self.sysconfig.nic       
         if nic.type == NetworkInfo.AUTOMATIC:
             network_summary.append(_("  Network Configuration: Automatic"))
         elif nic.type == NetworkInfo.NONE:
@@ -186,4 +210,3 @@
         '''Return a string summary of the timezone selection'''
         timezone = self.sysconfig.system.tz_timezone
         return _("Time Zone: %s") % timezone
-
--- a/usr/src/cmd/system-config/svc/svc-system-config	Fri May 27 09:34:25 2011 +0100
+++ b/usr/src/cmd/system-config/svc/svc-system-config	Fri May 27 12:13:10 2011 +0200
@@ -54,17 +54,17 @@
 
 ETC_USER_ATTR=/etc/user_attr
 
-# path to SC profile generated by System Configuration Interactive (SCI) tool
-SCIT_SC_PROFILE="${TMP_DIR}/sc_profile.xml"
+# name of profile generated by System Configuration Interactive (SCI) tool
+SCIT_PROFILE="scit_profile.xml"
+
+# path to SC profile generated by SCI tool
+SCIT_PROFILE_SRC="${TMP_DIR}/${SCIT_PROFILE}"
 
 # smf profile directory
 SMF_PROFILE_DIR=/etc/svc/profile
 
 # target destination for SC profile generated by SCI tool
-SC_PROFILE_DST=${SMF_PROFILE_DIR}/sc_profile.xml
-
-# site profile
-SITE_PROFILE=${SMF_PROFILE_DIR}/site.xml
+SCIT_PROFILE_DST="${SMF_PROFILE_DIR}/${SCIT_PROFILE}"
 
 # property group definitions
 # configuration of user account
@@ -84,6 +84,19 @@
 INITIAL_DOT_PROFILE="$ETC_SKEL/$DOT_PROFILE"
 INITIAL_DOT_BASHRC="$ETC_SKEL/$DOT_BASHRC"
 
+#
+# List of configuration screens which are applicable
+# to particular running environment:
+#  - global zone: all screens
+#  - non-global zone with exclusive IP stack:
+#    skip configuration of date and time, keyboard layout
+#  - non-global zone with shared IP stack:
+#    skip configuration of date and time, keyboard layout, networking
+#
+SCI_SCREENS_GZ="system"
+SCI_SCREENS_NGZ_IP_EXCLUSIVE="identity,network,naming_services,location,users"
+SCI_SCREENS_NGZ_IP_SHARED="identity,naming_services,location,users"
+
 # configuration properties
 # enable system configuration
 PROP_CONFIGURE="$PG_CONFIGURATION/configure"
@@ -1198,7 +1211,7 @@
 	print -u1 " Interactive configuration requested," \
 	    "bringing up System Configuration Interactive tool."
 
-	if [[ ! -x "/usr/bin/sysconfig" ]] ; then
+	if [[ -z $(which sysconfig 2>/dev/null) ]] ; then
 		print -u1 " SCI tool not found," \
 		    "skipping interactive configuration."
 
@@ -1232,7 +1245,36 @@
 		fi
 	fi
 
-	SC_FILE=$SCIT_SC_PROFILE sysconfig < /dev/console > /dev/console 2>&1
+	#
+	# Construct list of configuration screens which are applicable
+	# to current running environment.
+	# Initially assume that we are in global zone.
+	#
+	typeset sci_screens=$SCI_SCREENS_GZ
+
+	if smf_is_nonglobalzone; then
+		typeset zone_type=$(zonename -t)
+
+		if (( $? != 0 )) ; then
+			print -u2 "Could not detect type of non-global zone," \
+			    "aborting."
+			exit $SMF_EXIT_ERR_FATAL
+		fi
+
+		print -u1 " Detected running environment: non-global zone" \
+		    "with <$zone_type> IP stack."
+
+		if [[ "$zone_type" == "shared" ]]; then
+			sci_screens=$SCI_SCREENS_NGZ_IP_SHARED
+		else
+			sci_screens=$SCI_SCREENS_NGZ_IP_EXCLUSIVE
+		fi
+	else
+		print -u1 " Detected running environment: global zone."
+	fi
+
+	sysconfig create-profile -g $sci_screens -o $SCIT_PROFILE_SRC \
+	    < /dev/console > /dev/console 2>&1
 	typeset -i ret=$?
 
 	# if SCI tool failed to create SC profile, abort
@@ -1240,7 +1282,7 @@
 		print -u2 -f "%s%d%s\n" \
 		    "SCI tool failed to create SC profile, (ret=" \
 		    $ret \
-		    ", aborting."
+		    "), aborting."
 
 		exit $SMF_EXIT_ERR_FATAL
 	fi
@@ -1249,7 +1291,7 @@
 	# If SCI tool didn't generate SC profile (for instance when user
 	# prematurely quit the application), return.
 	#
-	if [[ ! -r $SCIT_SC_PROFILE ]] ; then
+	if [[ ! -r $SCIT_PROFILE_SRC ]] ; then
 		print -u1 " SCI tool did not create SC profile," \
 		    "skipping the rest of interactive configuration."
 
@@ -1257,11 +1299,11 @@
 	fi
 
 	# move created SC profile to the directory dedicated for smf profiles
-	mv $SCIT_SC_PROFILE $SC_PROFILE_DST
+	mv $SCIT_PROFILE_SRC $SCIT_PROFILE_DST
 
 	if (( $? != 0 )) ; then
-		print -u2 "Failed to move $SCIT_SC_PROFILE" \
-                    "to $SC_PROFILE_DST, aborting."
+		print -u2 "Failed to move $SCIT_PROFILE_SRC" \
+                    "to $SCIT_PROFILE_DST, aborting."
 
 		exit $SMF_EXIT_ERR_FATAL
 	fi
@@ -1299,44 +1341,25 @@
 		fi
 
 		# If exists, apply System Configuration profile.
-		if [[ -r $SC_PROFILE_DST ]] ; then
-			print -u1 " Applying $SC_PROFILE_DST SC profile."
+		if [[ -r $SCIT_PROFILE_DST ]] ; then
+			print -u1 " Applying $SCIT_PROFILE_DST SC profile."
 
-			svccfg apply $SC_PROFILE_DST
+			svccfg apply $SCIT_PROFILE_DST
 
 			if (( $? != 0 )) ; then
 				print -u2 "svccfg(1M) failed to apply" \
-	        	            "$SC_PROFILE_DST, aborting."
+	        	            "$SCIT_PROFILE_DST, aborting."
 
 				exit $SMF_EXIT_ERR_FATAL
 			fi
 		else
-			print -u1 " $SC_PROFILE_DST does not exist," \
+			print -u1 " $SCIT_PROFILE_DST does not exist," \
 			    "skipping step of applying System Configuration" \
 			    "profile."
 		fi
 
 		# System configuration succeeded, reset configure property.
 		set_smf_prop $SMF_FMRI $PROP_CONFIGURE false
-	fi
-
-	#
-	# remove site.xml link pointing to System Configuration profile.
-	# This is workaround for the fact that the profile is applied during
-	# both Early as well as Late Manifest Import process. We need to assure
-	# that the profile is applied only once, so that configuration process
-	# is not run twice during first boot.
-	#
-
-	if [[ -L "$SITE_PROFILE" ]] ; then
-		rm "$SITE_PROFILE"
-
-		if (( $? != 0 )) ; then
-			print -u2 "Failed to remove $SITE_PROFILE link," \
-			    "aborting."
-
-			exit $SMF_EXIT_ERR_FATAL
-		fi
 
 		print -u1 "System successfully configured."
 	fi
--- a/usr/src/cmd/system-config/test/test_summary.py	Fri May 27 09:34:25 2011 +0100
+++ b/usr/src/cmd/system-config/test/test_summary.py	Fri May 27 12:13:10 2011 +0200
@@ -104,53 +104,3 @@
         user_summary = self.summary.get_users()
         self.assertTrue("  Username: test" in user_summary,
                         '"Username: test" not in "%s"' % user_summary)
-    
-    def test_get_networks_auto(self):
-        '''SummaryScreen.get_networks() displays properly for AUTOMATIC'''
-        nic = MockAll()
-        nic.type = NetworkInfo.AUTOMATIC
-        self.summary.sysconfig.nic = nic
-        self.summary.sysconfig.system.hostname = "test-hostname"
-        
-        net_summary = self.summary.get_networks()
-        self.assertEquals("  Computer name: test-hostname", net_summary[0])
-        self.assertEquals("  Network Configuration: Automatic", net_summary[1])
-        self.assertEquals(2, len(net_summary))
-    
-    def test_get_networks_manual(self):
-        '''SummaryScreen.get_networks() displays properly for MANUAL'''
-        nic = MockAll()
-        nic.type = NetworkInfo.MANUAL
-        self.summary.sysconfig.nic = nic
-        self.summary.sysconfig.system.hostname = "test-hostname"
-        
-        net_summary = self.summary.get_networks()
-        self.assertEquals("  Computer name: test-hostname", net_summary[0])
-        
-        summary_str = "\n".join(net_summary)
-        self.assertTrue("Manual Configuration:" in summary_str)
-        self.assertTrue("IP Address:" in summary_str)
-        self.assertTrue("Netmask:" in summary_str)
-    
-    def test_get_networks_none(self):
-        '''SummaryScreen.get_networks() displays properly for NONE'''
-        nic = MockAll()
-        nic.type = NetworkInfo.NONE
-        self.summary.sysconfig.nic = nic
-        self.summary.sysconfig.system.hostname = "test-hostname"
-        
-        net_summary = self.summary.get_networks()
-        self.assertEquals("  Computer name: test-hostname", net_summary[0])
-        self.assertEquals("  Network Configuration: None", net_summary[1])
-        self.assertEquals(2, len(net_summary))
-    
-    def test_build_summary(self):
-        '''SummaryScreen.build_summary() fills in keyboard, languages, etc.'''
-        self.summary.sysconfig.system.locale = "test-locale"
-        self.summary.sysconfig.actual_lang = "test-lang"
-        self.summary.sysconfig.system.keyboard = "test-keyboard"
-        
-        summary = self.summary.build_summary()
-        
-        self.assertTrue("Default language: test-lang" in summary)
-        self.assertTrue("Default keyboard layout: test-keyboard" in summary)
--- a/usr/src/cmd/system-config/test/test_sysconfig.py	Fri May 27 09:34:25 2011 +0100
+++ b/usr/src/cmd/system-config/test/test_sysconfig.py	Fri May 27 12:13:10 2011 +0200
@@ -37,23 +37,28 @@
 
 
 class TestSysconfig(unittest.TestCase):
+    def test_parse_options_subcommand(self):
+        '''parse_options() returns proper subcommmand'''
+        (options, sub_cmd) = sysconfig._parse_options(["create-profile"])
+        self.assertEqual(sub_cmd[0], "create-profile")
     
     def test_parse_options_no_flags(self):
         '''parse_options() returns proper default options'''
-        options = sysconfig._parse_options([])
+        (options, sub_cmd) = sysconfig._parse_options(["create-profile"])
         self.assertEqual(options.logname, sysconfig.DEFAULT_LOG_LOCATION)
         self.assertEqual(options.log_level,
                          getattr(logging, sysconfig.DEFAULT_LOG_LEVEL.upper()))
         self.assertFalse(options.force_bw)
-        self.assertFalse(options.dry_run)
         self.assertFalse(options.debug)
     
     def test_parse_options_accepts_flags(self):
-        '''parse_options() accepts "-l <log>", "-b", and "-n"'''
-        options = sysconfig._parse_options(["-l", "/foo/log.txt", "-b", "-n"])
+        '''parse_options() accepts "create-profile -l <log> -b -o <profile>"'''
+        (options, sub_cmd) = sysconfig._parse_options(["create-profile", "-l",
+                                                       "/foo/log.txt", "-b",
+                                                       "-o", "/foo/sc.xml"])
         self.assertEqual(options.logname, "/foo/log.txt")
+        self.assertEqual(options.profile, "/foo/sc.xml")
         self.assertTrue(options.force_bw)
-        self.assertTrue(options.dry_run)
     
     def test_parse_options_log_level_valid(self):
         '''parse_options() properly reformats error, warn, info,
@@ -61,7 +66,8 @@
         levels = ["error", "warn", "info", "debug"]
         
         for level in levels:
-            options = sysconfig._parse_options(["-v", level])
+            (options, sub_cmd) = sysconfig._parse_options(["create-profile",
+                                                           "-v", level])
             self.assertEqual(options.log_level,
                              getattr(logging, level.upper()))
             if level == "debug":
@@ -69,10 +75,12 @@
             else:
                 self.assertFalse(options.debug)
         
-        options = sysconfig._parse_options(["-v", "input"])
+        (options, sub_cmd) = sysconfig._parse_options(["create-profile", "-v",
+                                                       "input"])
         self.assertEqual(options.log_level, sysconfig.LOG_LEVEL_INPUT)
         self.assertTrue(options.debug)
     
     def test_parse_options_invalid_log_level(self):
         '''parse_options() rejects unsupported log levels'''
-        self.assertRaises(SystemExit, sysconfig._parse_options, ["-v", "foo"])
+        self.assertRaises(SystemExit, sysconfig._parse_options,
+                          ["create-profile", "-v", "foo"])
--- a/usr/src/cmd/system-config/welcome.py	Fri May 27 09:34:25 2011 +0100
+++ b/usr/src/cmd/system-config/welcome.py	Fri May 27 12:13:10 2011 +0200
@@ -26,7 +26,10 @@
 Contains the Welcome Screen for the SCI Tool
 '''
 
-from solaris_install.sysconfig import _, SCI_HELP
+from solaris_install.sysconfig import _, SCI_HELP, get_sc_options_from_doc, \
+                                      configure_group, SC_GROUP_IDENTITY, \
+                                      SC_GROUP_NETWORK, SC_GROUP_DATETIME, \
+                                      SC_GROUP_LOCATION, SC_GROUP_USERS
 from terminalui.base_screen import BaseScreen
 
 
@@ -40,10 +43,7 @@
     WELCOME_TEXT = _("System Configuration Tool enables you to specify "
                      "the following configuration parameters for your "
                      "newly-installed Oracle Solaris 11 system:\n"
-                     "- network\n"
-                     "- time zone\n"
-                     "- date and time\n"
-                     "- user and root accounts\n\n"
+                     "%(scgroups)s\n"
                      "System Configuration Tool produces an SMF profile file "
                      "in %(scprof)s.\n\n"
                      "How to navigate through this tool:")
@@ -65,10 +65,25 @@
         self.main_win.actions.pop(self.main_win.back_action.key, None)
     
     def _show(self):
-        '''Display the static paragraph WELCOME_TEXT and all bullet items'''
+        '''Display the static paragraph WELCOME_TEXT and all
+           applicable bullet items'''
+        sc_options = get_sc_options_from_doc()
+        sc_groups = ""
+        if configure_group(SC_GROUP_NETWORK):
+            sc_groups += _("- network\n")
+        elif configure_group(SC_GROUP_IDENTITY):
+            sc_groups += _("- system hostname\n")
+        if configure_group(SC_GROUP_LOCATION):
+            sc_groups += _("- time zone\n")
+        if configure_group(SC_GROUP_DATETIME):
+            sc_groups += _("- date and time\n")
+        if configure_group(SC_GROUP_USERS):
+            sc_groups += _("- user and root accounts\n")
+
+        fmt = {"scgroups": sc_groups, "scprof": sc_options.profile}
+        text = WelcomeScreen.WELCOME_TEXT % fmt
+
         y_loc = 1
-        fmt = {"scprof" : "/tmp/sc_manifest.xml"}
-        text = WelcomeScreen.WELCOME_TEXT % fmt
         y_loc += self.center_win.add_paragraph(text, start_y=y_loc)
         x_loc = len(WelcomeScreen.BULLET)
         for bullet in WelcomeScreen.BULLET_ITEMS:
--- a/usr/src/pkg/manifests/system-install-configuration.mf	Fri May 27 09:34:25 2011 +0100
+++ b/usr/src/pkg/manifests/system-install-configuration.mf	Fri May 27 12:13:10 2011 +0200
@@ -29,7 +29,7 @@
 set name=variant.arch value=$(ARCH)
 
 dir path=usr group=sys
-dir path=usr/bin
+dir path=usr/sbin
 dir path=usr/lib
 dir path=usr/lib/python2.6
 dir path=usr/lib/python2.6/vendor-packages
@@ -41,7 +41,7 @@
 dir path=usr/share/sysconfig/help/C group=sys
 dir path=usr/share/sysconfig/xslt group=sys
 
-file path=usr/bin/sysconfig mode=0555
+file path=usr/sbin/sysconfig mode=0555
 
 file path=usr/lib/python2.6/vendor-packages/solaris_install/sysconfig/__init__.py mode=0444
 file path=usr/lib/python2.6/vendor-packages/solaris_install/sysconfig/__init__.pyc mode=0444