6971585 Solaris Next text installer should support network boot/data storage
authorAndrew Gracey, Chris Navrides, Keith Mitchell <keith.mitchell@oracle.com>
Fri, 07 Jan 2011 14:58:42 -0800
changeset 976 5430f542fce5
parent 975 051cadb9cf94
child 977 573afa5884d7
6971585 Solaris Next text installer should support network boot/data storage 7010312 Text Install failures occurring prior to updating system time freeze system
.hgignore
usr/src/cmd/distro_const/checkpoints/grub_setup.py
usr/src/cmd/distro_const/checkpoints/pkg_img_mod.py
usr/src/cmd/distro_const/manifest/dc_ai_sparc.xml
usr/src/cmd/distro_const/manifest/dc_ai_x86.xml
usr/src/cmd/installadm/installadm-common.sh
usr/src/cmd/slim-install/finish/install-finish
usr/src/cmd/slim-install/svc/net-fs-root
usr/src/cmd/text-install/osol_install/text_install/ti_install.py
usr/src/lib/libict_pymod/ict.py
usr/src/lib/liborchestrator/perform_slim_install.c
usr/src/pkg/manifests/system-install-text-install.mf
--- a/.hgignore	Wed Jan 05 13:37:29 2011 -0800
+++ b/.hgignore	Fri Jan 07 14:58:42 2011 -0800
@@ -18,7 +18,7 @@
 #
 # CDDL HEADER END
 #
-# Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
 #
 
 
@@ -67,6 +67,7 @@
 ^usr/src/cmd/installadm/setup-service$
 ^usr/src/cmd/installadm/setup-sparc$
 ^usr/src/cmd/installadm/setup-tftp-links$
+^usr/src/cmd/js2ai/js2ai$
 ^usr/src/cmd/slim-install/finish/install-finishc$
 ^usr/src/cmd/slim-install/user/jack/\.os-icons-installed$
 ^usr/src/cmd/slim-install/listcd/listcd$
--- a/usr/src/cmd/distro_const/checkpoints/grub_setup.py	Wed Jan 05 13:37:29 2011 -0800
+++ b/usr/src/cmd/distro_const/checkpoints/grub_setup.py	Fri Jan 07 14:58:42 2011 -0800
@@ -21,7 +21,7 @@
 #
 
 #
-# Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
 #
 
 """ grub_setup.py - Creates a custom grub menu.lst file
@@ -82,9 +82,9 @@
         self.img_info_path = os.path.join(self.pkg_img_path, ".image_info")
         self.menu_list = os.path.join(self.pkg_img_path, "boot/grub/menu.lst")
 
-        # retreive manifest specific grub configurations
+        # retrieve manifest specific grub configurations
         grub_mods = self.doc.volatile.get_descendants(class_type=GrubMods)
-        if len(grub_mods) == 0:    
+        if len(grub_mods) == 0:
             # if there are no GrubMods in the doc, create a new GrubMods
             # instance and allow it to be populated with default values
             self.grub_mods = GrubMods("grub mods")
@@ -178,20 +178,18 @@
         self.write_entries(entries)
 
 
-class AIGrubSetup(GrubSetup, Checkpoint):
+class AIGrubSetup(GrubSetup):
     """ AIGrubSetup - class to customize the grub menu for AI distributions
     """
-
-    def __init__(self, name):
-        """ constructor for class.
-        """
-        super(AIGrubSetup, self).__init__(name)
-
-    def get_progress_estimate(self):
-        """Returns an estimate of the time this checkpoint will take
-        """
-        return 1
-
+    
+    def __init__(self, name, arg=None):
+        GrubSetup.__init__(self, name)
+        if arg:
+            self.__setup(**arg)
+    
+    def __setup(self, installadm_entry="boot image"):
+        self.installadm_entry = installadm_entry
+    
     def build_entries(self):
         """ class method for constructing the entries list.
         """
@@ -236,6 +234,7 @@
         with open(self.img_info_path, "a+") as iip:
             iip.write("GRUB_MIN_MEM64=%s\n" % self.grub_mods.min_mem)
             iip.write("GRUB_DO_SAFE_DEFAULT=true\n")
+            iip.write("NO_INSTALL_GRUB_TITLE=%s\n" % self.installadm_entry)
 
     def execute(self, dry_run=False):
         """ Primary execution method used by the Checkpoint parent class.
--- a/usr/src/cmd/distro_const/checkpoints/pkg_img_mod.py	Wed Jan 05 13:37:29 2011 -0800
+++ b/usr/src/cmd/distro_const/checkpoints/pkg_img_mod.py	Fri Jan 07 14:58:42 2011 -0800
@@ -21,7 +21,7 @@
 #
 
 #
-# Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
 #
 
 """ pkg_img_mod
@@ -277,6 +277,25 @@
                 fh.write(entry + "\n")
 
         os.chdir(cwd)
+    
+    def create_save_list(self):
+        '''Store a list of files under the 'save' directory. Net-booted
+        text installer uses this list to determine what files it needs from
+        the boot server
+        
+        '''
+        save_files = []
+        save_dir = os.path.join(self.pkg_img_path, "save")
+        for root, d, files in os.walk(save_dir):
+            for f in files:
+                relpath = os.path.relpath(os.path.join(root, f),
+                                          start=self.pkg_img_path)
+                save_files.append(relpath)
+        
+        save_list = os.path.join(self.pkg_img_path, "save_list")
+        with open(save_list, "w") as save_fh:
+            for entry in save_files:
+                save_fh.write(entry + "\n")
 
     def execute(self, dry_run=False):
         """Customize the pkg_image area. Assumes that a populated pkg_image
@@ -295,6 +314,8 @@
 
         # create the /mnt/misc archive
         self.create_misc_archive()
+        
+        self.create_save_list()
 
 
 class LiveCDPkgImgMod(PkgImgMod, Checkpoint):
@@ -358,52 +379,8 @@
         self.create_livecd_content_file()
 
 
-class AIPkgImgMod(PkgImgMod, Checkpoint):
-    """ AIPkgImgMod - class to modify the pkg_image directory after to boot
-    archive is built for AI distributions
-    """
-
-    DEFAULT_ARG = {"compression_type": "gzip"}
-
-    def __init__(self, name, arg=DEFAULT_ARG):
-        super(AIPkgImgMod, self).__init__(name, arg)
-
-    def execute(self, dry_run=False):
-        """ Customize the pkg_image area. Assumes that a populated pkg_image
-        area exists and that the boot_archive has been built
-        """
-        self.logger.info("=== Executing Pkg Image Modification Checkpoint ===")
-
-        self.parse_doc()
-
-        # clean up the root of the package image path
-        self.strip_root()
-
-        # create the /usr archive
-        self.create_usr_archive()
-
-        # create the /mnt/misc archive
-        self.create_misc_archive()
-
-        # get the platform of the system
-        arch = platform.processor()
-
-        # save the current working directory
-        cwd = os.getcwd()
-
-        # clean up the package image path based on the platform
-        if arch == "i386":
-            self.strip_x86_platform()
-        else:
-            self.strip_sparc_platform()
-
-        # return to the initial directory
-        os.chdir(cwd)
-
-# The only difference between TextPkgImgMod and AIPkgImgMod
-# is the creation of the .livecd_content file
 class TextPkgImgMod(PkgImgMod, Checkpoint):
-    """ TextPkgImgMod - class to modify the pkg_image directory after to boot
+    """ TextPkgImgMod - class to modify the pkg_image directory after the boot
     archive is built for Text media
     """
 
@@ -434,15 +411,27 @@
 
         # save the current working directory
         cwd = os.getcwd()
+        try:
+            # clean up the package image path based on the platform
+            if arch == "i386":
+                self.strip_x86_platform()
+            else:
+                self.strip_sparc_platform()
+    
+            # create the .livecd-cdrom-content file
+            self.create_livecd_content_file()
+        finally:
+            # return to the initial directory
+            os.chdir(cwd)
+        
+        self.create_save_list()
 
-        # clean up the package image path based on the platform
-        if arch == "i386":
-            self.strip_x86_platform()
-        else:
-            self.strip_sparc_platform()
-
-        # create the .livecd-cdrom-content file
-        self.create_livecd_content_file()
-
-        # return to the initial directory
-        os.chdir(cwd)
+# Currently, no difference between AIPkgImgMod and TextPkgImgMod.
+# Defined as an empty subclass here so that manifests can
+# reference AIPkgImgMod now, and if the classes diverge,
+# old manifests won't need updating
+class AIPkgImgMod(TextPkgImgMod):
+    """ AIPkgImgMod - class to modify the pkg_image directory after the boot
+    archive is built for AI distributions
+    """
+    pass
--- a/usr/src/cmd/distro_const/manifest/dc_ai_sparc.xml	Wed Jan 05 13:37:29 2011 -0800
+++ b/usr/src/cmd/distro_const/manifest/dc_ai_sparc.xml	Fri Jan 07 14:58:42 2011 -0800
@@ -20,7 +20,7 @@
  
   CDDL HEADER END
  
-  Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+  Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
 
   XML specification for building an Oracle Solaris installer iso image
 -->
@@ -95,6 +95,7 @@
       <software_data action="install" type="IPS">
         <name>pkg:/entire</name>
         <name>pkg:/system/install/media/internal</name>
+        <name>pkg:/system/install/text-install</name>
         <name>pkg:/auto_install</name>
       </software_data>
       <software_data action="uninstall" type="IPS">
--- a/usr/src/cmd/distro_const/manifest/dc_ai_x86.xml	Wed Jan 05 13:37:29 2011 -0800
+++ b/usr/src/cmd/distro_const/manifest/dc_ai_x86.xml	Fri Jan 07 14:58:42 2011 -0800
@@ -20,7 +20,7 @@
  
   CDDL HEADER END
  
-  Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+  Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
 
   XML specification for building an Oracle Solaris installer iso image
 -->
@@ -135,6 +135,7 @@
       <software_data action="install" type="IPS">
         <name>pkg:/entire</name>
         <name>pkg:/system/install/media/internal</name>
+        <name>pkg:/system/install/text-install</name>
         <name>pkg:/auto_install</name>
       </software_data>
       <software_data action="uninstall" type="IPS">
@@ -265,6 +266,11 @@
           desc="Setup GRUB menu"
           mod_path="solaris_install/distro_const/checkpoints/grub_setup"
           checkpoint_class="AIGrubSetup">
+          <kwargs>
+            <!-- The installadm_entry defines the title for the default
+            Grub entry used by installadm when unpacking the image for use -->
+            <arg name="installadm_entry">Text Installer and command line</arg>
+          </kwargs>
       </checkpoint>
       <checkpoint name="pkg-img-mod"
           desc="Pkg image area modification"
--- a/usr/src/cmd/installadm/installadm-common.sh	Wed Jan 05 13:37:29 2011 -0800
+++ b/usr/src/cmd/installadm/installadm-common.sh	Fri Jan 07 14:58:42 2011 -0800
@@ -19,7 +19,7 @@
 #
 # CDDL HEADER END
 #
-# Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
 #
 # Description:
 #       It contains common functions used by create-client and
@@ -74,6 +74,7 @@
 GRUB_TITLE_KEYWORD="GRUB_TITLE"
 GRUB_MIN_MEM64="GRUB_MIN_MEM64"
 GRUB_DO_SAFE_DEFAULT="GRUB_DO_SAFE_DEFAULT"
+NO_INSTALL_GRUB_MENU="NO_INSTALL_GRUB_TITLE"
 NETBOOTDIR="/etc/netboot"
 WANBOOT_CONF_FILE="wanboot.conf"
 SPARC_INSTALL_CONF="install.conf"
@@ -406,6 +407,46 @@
 }
 
 #
+# get_grub_text_mode_menu
+#
+# Purpose: Get the title to be used for the default menu option
+#
+# Arguments:
+#      $1 - path to image 
+#
+# Returns: string with menu title 
+#
+get_grub_text_mode_menu()
+{
+	
+	grub_text_mode_menu=""
+
+	image_info_path=$1/${DOT_IMAGE_INFO}
+	if [[ -f ${image_info_path} ]]; then
+                while read line ; do
+                        if [[ "${line}" == ~(E)^${NO_INSTALL_GRUB_MENU}=.* ]]
+                        then
+                                grub_text_mode_menu="${line#*=}"
+                        fi
+                done < ${image_info_path}
+        fi
+
+	# Default to the value in .release or VERSION to remain consistent
+	# If there is not a title specified in .image_info we assume that 
+	# the image doesn't have the text install capability
+	if [[ -z "${grub_text_mode_menu}" ]]; then
+		releasepath=$1/${DOT_RELEASE}
+		if [[ -f ${releasepath} ]]; then
+			grub_text_mode_menu=$(head -1 ${releasepath})
+		else
+			grub_text_mode_menu=$VERSION
+		fi
+		grub_text_mode_menu="$grub_text_mode_menu boot image"
+	fi
+
+	print "$grub_text_mode_menu"
+}
+#
 # get_service_address
 #
 # Purpose: Get the service location (machine ip and port number) for a given
@@ -878,6 +919,8 @@
 	# get release info and strip leading spaces
 	typeset grub_title_string=$(get_grub_title ${IMAGE_PATH})
 	typeset title="title ${grub_title_string//  /}"
+	typeset text_title_string=$(get_grub_text_mode_menu ${IMAGE_PATH})
+	typeset text_title="title ${text_title_string//  /}"
 
 	# get flag indicating whether or not to create a safe default
 	# entry in the menu (i.e. a default entry that does not start
@@ -892,7 +935,7 @@
 
 	if [ "$grub_do_safe_default" = "true" ] ; then
 		# title and kernel lines for safe default entry.
-		tmpent1+="${title} boot image\n"
+		tmpent1+="${text_title}\n"
 		tmpent1+="\tkernel\$ /${BootLofs}/platform/i86pc/kernel/\$ISADIR/unix -B ${BARGLIST}"
 
 		# append to automated install entry.
--- a/usr/src/cmd/slim-install/finish/install-finish	Wed Jan 05 13:37:29 2011 -0800
+++ b/usr/src/cmd/slim-install/finish/install-finish	Fri Jan 07 14:58:42 2011 -0800
@@ -19,7 +19,7 @@
 #
 # CDDL HEADER END
 #
-# Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
 '''
 perform all Python Slim Install Completion Tasks (ICT)
 
@@ -31,6 +31,7 @@
 
 Parameters:
         target root pathname - required
+        installer type -required (AI/TEXT/LIVE)
         debugging level (if invalid, ignored)
 
 This Python script has been taken from the former install-finish shell script
@@ -52,28 +53,6 @@
     LS_DBGLVL_INFO, \
     LS_DBGLVL_WARN
 
-# Test to see if running in an automated install environment
-def autoinstall_exists():
-    '''
-    autoinstall_exists - Determine if this script is being
-    invoked from an Automated Install.
-    '''
-    if os.path.exists('/.autoinstall'):
-        return 1
-    else:
-        return 0
-
-# Test to see if running in a text install environment
-def textinstall_exists():
-    '''
-    textinstall_exists - Determine if this script is being
-    invoked from a Text Install.
-    '''
-    if os.path.exists('/.textinstall'):
-        return 1
-    else:
-        return 0
-
 # Test to see if running on a SPARC platform
 IS_SPARC = (platform.platform().find('sparc') >= 0)
 
@@ -82,21 +61,22 @@
 BASEDIR = ""           # argument B
 USER_SPEC_DBGLVL = ""  # argument d
 ROOT_PW = ""           # argument R
-NU_GOS  = ""           # argument n
+NU_GOS = ""            # argument n
 NU_LOGIN = ""          # argument l
 NU_PW = ""             # argument p
 NU_GID = "101"         # argument G
 NU_UID = "10"          # argument U
 NO_NETWORK = False     # argument N
-
+INST_TYPE = ""         # argument I
 #parse command line arguments
 try:
-    OPTS, ARGS = getopt.getopt(sys.argv[1:],'B:d:R:n:l:p:G:U:N')
+    OPTS, ARGS = getopt.getopt(sys.argv[1:], 'B:d:R:n:l:p:G:U:I:N')
 
 except getopt.GetoptError, err:
     prerror('Parsing command line arguments failed. (%s)' % str(err))
 
     prerror('Usage: -B <target basedir>')
+    prerror('       -I <Installer type> - AI/TEXT/LIVE')
     prerror('       [-d <debug level>] -  LS_DBGLVL_EMERG ' +
             'LS_DBGLVL_ERR LS_DBGLVL_WARN LS_DBGLVL_INFO')
     prerror('       [-R <root password>] - default is blank')
@@ -110,27 +90,32 @@
     sys.exit(ICT_INVALID_PARAMETER)
 
 for o, a in OPTS:
-    if o in '-B':
+    if o == '-B':
         BASEDIR = a
-    if o in '-d':
+    if o == '-d':
         USER_SPEC_DBGLVL = a
-    if o in '-R':
+    if o == '-R':
         ROOT_PW = a
-    if o in '-n':
-        NU_GOS  = a
-    if o in '-l':
+    if o == '-n':
+        NU_GOS = a
+    if o == '-l':
         NU_LOGIN = a
-    if o in '-p':
+    if o == '-p':
         NU_PW = a
-    if o in '-G':
+    if o == '-G':
         NU_GID = a
-    if o in '-U':
+    if o == '-U':
         NU_UID = a
-    if o in '-N':
+    if o == '-I':
+        INST_TYPE = a
+    if o == '-N':
         NO_NETWORK = True
 
 #perform ICT initialization, specifying root target path, debugging level
-
+if INST_TYPE not in ('TEXT', 'AI', 'LIVE'):
+    prerror('caller must provide type of install. AI/TEXT/LIVE')
+    prerror('was passed -I flag of %s' % INST_TYPE)
+    sys.exit(ICT_INVALID_PARAMETER)
 if not BASEDIR:
     prerror('caller must provide the root target directory.')
     sys.exit(ICT_INVALID_PARAMETER)
@@ -165,7 +150,7 @@
 
 SA = [] #init array of return statuses
 
-if autoinstall_exists():
+if INST_TYPE == 'AI':
     # Doing an automated install
 
     if IS_SPARC:
@@ -210,7 +195,6 @@
 
 else:
     # Doing a GUI install or a Text Install
-
     # At this time there is no SPARC specific processed needed for GUI install
     # SPARC specific processing is needed for Text Install
 
@@ -236,30 +220,30 @@
         SA.append(ICTO.copy_sparc_bootlst())
     else:
         SA.append(ICTO.explicit_bootfs())
-        if not textinstall_exists():
+        if INST_TYPE != 'TEXT':
             SA.append(ICTO.enable_happy_face_boot())
     if not IS_SPARC:
         SA.append(ICTO.copy_splash_xpm())
     SA.append(ICTO.smf_correct_sys_profile())
     SA.append(ICTO.add_sysidtool_sys_unconfig())
-    if textinstall_exists():
-        PKG_REMOVE_LIST = ['pkg:/system/install/media/internal',
-                           'pkg:/system/install/text-install']
-    else:
-        # GUI installer
-        PKG_REMOVE_LIST = ['pkg:/system/install/media/internal',
-                           'pkg:/system/install/gui-install',
-			   'pkg:/system/install/locale']
+    
     if NO_NETWORK:
         SA.append(ICTO.do_not_configure_network())
     else:
         SA.append(ICTO.enable_nwam())
 
     SA.append(ICTO.remove_livecd_environment())
+    
+    # packages that are not installed are ignored
+    PKG_REMOVE_LIST = ['pkg:/system/install/media/internal',
+                       'pkg:/system/install/text-install',
+                       'pkg:/system/install/gui-install',
+                       'pkg:/system/install/locale']
+    
     SA.append(ICTO.remove_specific_packages(PKG_REMOVE_LIST))
     SA.append(ICTO.set_flush_content_cache_false())
     # Password is pre-expired in GUI case since user didn't explicitly set it
-    SA.append(ICTO.set_root_password(ROOT_PW, not textinstall_exists()))
+    SA.append(ICTO.set_root_password(ROOT_PW, INST_TYPE != 'TEXT'))
     SA.append(ICTO.create_new_user(NU_GOS, NU_LOGIN, NU_PW, NU_GID, NU_UID))
     SA.append(ICTO.set_homedir_map(NU_LOGIN))
     SA.append(ICTO.setup_rbac(NU_LOGIN))
@@ -279,7 +263,7 @@
 if ERRCOUNT > 0:
     info_msg(str(ERRCOUNT) + ' out of ' + str(len(SA)) +
         ' total Python ICTs finished with errors')
-    sys.exit(1) #signal script completed, exiting with failure status
+    sys.exit(1) # signal script completed, exiting with failure status
 else:
     info_msg('All ' + str(len(SA)) + ' Python ICTs finished successfully')
-    sys.exit(0) #signal script completed, exiting with success status
+    sys.exit(0) # signal script completed, exiting with success status
--- a/usr/src/cmd/slim-install/svc/net-fs-root	Wed Jan 05 13:37:29 2011 -0800
+++ b/usr/src/cmd/slim-install/svc/net-fs-root	Fri Jan 07 14:58:42 2011 -0800
@@ -20,7 +20,7 @@
 # CDDL HEADER END
 #
 #
-# Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
 #
 
 # Make sure that the libraries essential to this stage of booting can be found.
@@ -28,6 +28,15 @@
 
 AUTOINSTALL=0
 
+#
+# Text Installer script
+#
+TI_SMF_SETUP="svc:/system/install-setup:default"
+CLI_LOGIN="svc:/system/console-login:default"
+MANIFEST_LOC="svc:/application/manifest-locator:default"
+SVCADM=/usr/sbin/svcadm
+TEXT_FLAG="true"
+
 PRTCONF=/usr/sbin/prtconf
 SED=/usr/bin/sed
 CUT=/usr/bin/cut
@@ -46,6 +55,13 @@
 TIMEOUT=900
 TRIES=20
 
+# Image Info file (needed for x86 AI, and both for Text Installs)
+IMAGE_INFO=".image_info"
+
+# Save folder information (needed for Text Installs)
+SAVE="save"
+SAVE_LIST="save_list"
+
 # Sparc installation configuration
 INSTALL_CONF_FILE="install.conf"
 INSTALL_CONF_SPEC="/tmp/$INSTALL_CONF_FILE"
@@ -73,7 +89,7 @@
 
 ISA_INFO=$(/sbin/uname -p)
 
-echo "Preparing automated install image for use" > /dev/msglog
+echo "Preparing install image for use" > /dev/msglog
 
 #
 # For SPARC mount wanbootfs which contains wanboot.conf file
@@ -150,6 +166,27 @@
 	fi
 
 	MEDIA="$ai_server$ai_image_dir"
+	
+	#
+	# Check if the install flag is present in the bootargs.
+	# If it is present then it will be an AI install,
+	# so set TEXT_FLAG to "false"
+	#
+	set -- `$PRTCONF -vp | $GREP "bootargs" | $CUT -f 2 -d\'`
+	while (( $# > 0 )) ; do
+		case $1 in
+
+		install)
+			TEXT_FLAG="false"
+			break
+			;;
+		*)
+			shift
+			;;
+		esac
+	done
+
+
 else
 	# Get the install media data to use in http url
 	MEDIA=$($PRTCONF -v /devices | \
@@ -178,6 +215,18 @@
 	fi
 
 
+	#
+	# Check if the install flag is present in the bootargs.
+	# If it is present then it will be an AI install,
+	# so set TEXT_FLAG to "false"
+	#
+	INSTALL_FLAG=`$PRTCONF -v /devices | \
+	    $SED -n "/'install'/{;n;p;}" | \
+	    $CUT -f 2 -d \'`
+
+	if [ "$INSTALL_FLAG" == "true" ] ;then 
+	    TEXT_FLAG="false"
+	fi
 fi
 
 #
@@ -187,7 +236,7 @@
 url=$MEDIA
 if [ -z "$url" ]
 then
-	echo "Could not determine source of automated install image" > \
+	echo "Could not determine source of install image" > \
 	    /dev/msglog
 	exit $SMF_EXIT_ERR_FATAL
 fi
@@ -200,16 +249,14 @@
 	exit $SMF_EXIT_ERR_FATAL
 fi
 
+config_file=""
 # download the install.conf file to get the service name for SPARC
 if [[ "$ISA_INFO" == "sparc" ]]; then
 	config_file="$INSTALL_CONF_FILE"
-# download the .image_info file for x86
-elif [[ "$ISA_INFO" != "sparc" ]]; then
-	config_file=".image_info"
 fi
 
 # Download compressed archives and configuration information all into tmp
-for file in $SOLARIS_ZLIB $SOLARISMISC_ZLIB $config_file; do
+for file in $SOLARIS_ZLIB $SOLARISMISC_ZLIB $IMAGE_INFO $config_file; do
 
 	print "Downloading $file" > /dev/msglog
 	cmd="$WGET --continue --tries=1 --timeout=$TIMEOUT ${url}/$file -O /tmp/$file"
@@ -272,7 +319,7 @@
 	echo "Could not mount /mnt/misc" > /dev/msglog
 	exit $SMF_EXIT_ERR_FATAL
 fi
-echo "Done mounting automated install image" > /dev/msglog
+echo "Done mounting install image" > /dev/msglog
 
 #
 # If requested, enable remote access via ssh
@@ -294,6 +341,75 @@
 fi
 
 #
+# TEXT_FLAG is used to tell if we are using the text install over net boot
+#
+if [ "$TEXT_FLAG" == "true" ]; then
+	if [ "$ISA_INFO" == "i386" ]; then
+		mkdir /tmp/amd64
+		mkdir -p /.cdrom/platform/i86pc/amd64
+		
+		TYPE=`isainfo -b` 
+		if [ "$TYPE" == "32" ]; then
+			$WGET $url/platform/i86pc/amd64/boot_archive -O /tmp/amd64/boot_archive > /dev/msglog 2>&1
+			if [ "$?" != "0" ]; then
+				echo "ERROR: Failed to download amd64 boot Archive" > /dev/msglog
+				exit $SMF_EXIT_ERR_FATAL
+			fi
+			ln -s /tmp/amd64/boot_archive /.cdrom/platform/i86pc/amd64/boot_archive
+		else
+			$WGET $url/platform/i86pc/boot_archive -O /tmp/boot_archive > /dev/msglog 2>&1
+			if [ "$?" != "0" ]; then
+				echo "ERROR: Failed to download i86pc boot Archive" > /dev/msglog
+				exit $SMF_EXIT_ERR_FATAL
+			fi
+			ln -s /tmp/boot_archive /.cdrom/platform/i86pc/boot_archive
+		fi
+	fi
+	
+	# Retrieve the 'save' files (needed by remove_livecd_environment ICT)
+	cd /tmp
+	$WGET -x -i $url/$SAVE_LIST > /dev/msglog 2>&1
+	if [ "$?" != "0" ]; then
+		echo "ERROR: Failed to download save folder contents" > /dev/msglog
+		exit $SMF_EXIT_ERR_FATAL
+	fi
+	save_folder=$(print $url | $SED 's#.*//##')/$SAVE
+	cd -
+
+	# When net-booted, only the contents of /.cdrom/save
+	# (catalogued in the save_list)
+	# are relevant to the '.livecd-cdrom-content' file
+	$WGET $url/$SAVE_LIST -O /tmp/.livecd-cdrom-content
+	
+
+	# Link all of the downloaded files to where they should be in order to mimick CD
+	ln -s /tmp/solarismisc.zlib /.cdrom/solarismisc.zlib
+	ln -s /.volsetid /.cdrom/.volsetid 
+	ln -s /tmp/.image_info /.cdrom/.image_info
+	ln -s /tmp/.livecd-cdrom-content /.cdrom/.livecd-cdrom-content
+	ln -s /tmp/$save_folder /.cdrom/save
+
+	$SVCADM disable -s $CLI_LOGIN 
+	if [ "$?" != "0" ]; then
+		echo "svcadm failed to disable client login" > /dev/msglog
+		exit $SMF_EXIT_ERR_FATAL
+	fi
+	#Disable manifest locator
+	$SVCADM disable -s $MANIFEST_LOC	
+	if [ "$?" != "0" ]; then
+		echo "svcadm failed to disable manifest locator" > /dev/msglog
+		exit $SMF_EXIT_ERR_FATAL
+	fi
+
+	# Enable the text install SMF scripts
+	$SVCADM enable  $TI_SMF_SETUP 
+	if [ "$?" != "0" ]; then
+		echo "svcadm failed to enable Text Install SMF script" > /dev/msglog
+		exit $SMF_EXIT_ERR_FATAL
+	fi
+fi
+
+#
 # Also mount /boot now so that things like keymap.sh can access
 # boot properties through eeprom.  Readonly isn't required because
 # /boot (and other pcfs filesystems) aren't fsck'ed at boot yet.
--- a/usr/src/cmd/text-install/osol_install/text_install/ti_install.py	Wed Jan 05 13:37:29 2011 -0800
+++ b/usr/src/cmd/text-install/osol_install/text_install/ti_install.py	Fri Jan 07 14:58:42 2011 -0800
@@ -19,7 +19,7 @@
 #
 # CDDL HEADER END
 #
-# Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
 #
 
 '''
@@ -361,100 +361,103 @@
        Raises InstallationError for any error occurred during install.
 
     '''
-    #
-    # The following information is needed for installation.
-    # Make sure they are provided before even starting
-    #
-
-    # locale
-    locale = install_profile.system.locale
-    logging.debug("default locale: %s", locale)
-
-    # timezone
-    timezone = install_profile.system.tz_timezone
-    logging.debug("time zone: %s", timezone)
-
-    # hostname
-    hostname = install_profile.system.hostname
-    logging.debug("hostname: %s", hostname)
-
-    ulogin = None 
-    user_home_dir = ""
-
-    root_user = install_profile.users[0]
-    root_pass = root_user.password
-
-    reg_user = install_profile.users[1]
-    ureal_name = reg_user.real_name
-    ulogin = reg_user.login_name
-    upass = reg_user.password
-
-    logging.debug("Root password: %s", root_pass)
-
-    if ulogin:
-        user_home_dir = "/export/home/" + ulogin
-        ZFS_SHARED_FS.insert(0, user_home_dir)
-        logging.debug("User real name: %s", ureal_name)
-        logging.debug("User login: %s", ulogin)
-        logging.debug("User password: %s", upass)
-
-    (inst_device, inst_device_size) = \
-              install_profile.disk.get_install_dev_name_and_size()
-    logging.debug("Installation Device Name: %s", inst_device)
-    logging.debug("Installation Device Size: %sMB", inst_device_size)
-
-    swap_dump = ti_utils.SwapDump()
-
-    min_inst_size = ti_utils.get_minimum_size(swap_dump)
-    logging.debug("Minimum required size: %sMB", min_inst_size)
-    if (inst_device_size < min_inst_size):
-        logging.error("Size of device specified for installation "
-                      "is too small")
-        logging.error("Size of install device: %sMB", inst_device_size)
-        logging.error("Minimum required size: %sMB", min_inst_size)
-        raise ti_utils.InstallationError
-
-    recommended_size = ti_utils.get_recommended_size(swap_dump)
-    logging.debug("Recommended size: %sMB", recommended_size)
-    if (inst_device_size < recommended_size):
-        # Warn users that their install target size is not optimal
-        # Just log the warning, but continue with the installation.
-        logging.warning("Size of device specified for installation is "
-                        "not optimal") 
-        logging.warning("Size of install device: %sMB", inst_device_size)
-        logging.warning("Recommended size: %sMB", recommended_size)
-
-    # Validate the value specified for timezone
-    if not tz_isvalid(timezone):
-        logging.error("Timezone value specified (%s) is not valid", timezone)
-        raise ti_utils.InstallationError
-
-    # Compute the time to set here.  It will be set after the rtc
-    # command is run, if on x86.
-    install_time = datetime.datetime.now() + install_profile.system.time_offset
+    try:
+        #
+        # The following information is needed for installation.
+        # Make sure they are provided before even starting
+        #
+    
+        # locale
+        locale = install_profile.system.locale
+        logging.debug("default locale: %s", locale)
+    
+        # timezone
+        timezone = install_profile.system.tz_timezone
+        logging.debug("time zone: %s", timezone)
+    
+        # hostname
+        hostname = install_profile.system.hostname
+        logging.debug("hostname: %s", hostname)
+    
+        ulogin = None 
+        user_home_dir = ""
+    
+        root_user = install_profile.users[0]
+        root_pass = root_user.password
+    
+        reg_user = install_profile.users[1]
+        ureal_name = reg_user.real_name
+        ulogin = reg_user.login_name
+        upass = reg_user.password
+    
+        logging.debug("Root password: %s", root_pass)
+    
+        if ulogin:
+            user_home_dir = "/export/home/" + ulogin
+            ZFS_SHARED_FS.insert(0, user_home_dir)
+            logging.debug("User real name: %s", ureal_name)
+            logging.debug("User login: %s", ulogin)
+            logging.debug("User password: %s", upass)
+    
+        (inst_device, inst_device_size) = \
+                  install_profile.disk.get_install_dev_name_and_size()
+        logging.debug("Installation Device Name: %s", inst_device)
+        logging.debug("Installation Device Size: %sMB", inst_device_size)
+    
+        swap_dump = ti_utils.SwapDump()
     
-    if platform.processor() == "i386":
-        #
-        # At this time, the /usr/sbin/rtc command does not work in alternate
-        # root.  It hard codes to use /etc/rtc_config.
-        # Therefore, we set the value for rtc_config in the live environment
-        # so it will get copied over to the alternate root.
+        min_inst_size = ti_utils.get_minimum_size(swap_dump)
+        logging.debug("Minimum required size: %sMB", min_inst_size)
+        if (inst_device_size < min_inst_size):
+            logging.error("Size of device specified for installation "
+                          "is too small")
+            logging.error("Size of install device: %sMB", inst_device_size)
+            logging.error("Minimum required size: %sMB", min_inst_size)
+            raise ti_utils.InstallationError
+    
+        recommended_size = ti_utils.get_recommended_size(swap_dump)
+        logging.debug("Recommended size: %sMB", recommended_size)
+        if (inst_device_size < recommended_size):
+            # Warn users that their install target size is not optimal
+            # Just log the warning, but continue with the installation.
+            logging.warning("Size of device specified for installation is "
+                            "not optimal") 
+            logging.warning("Size of install device: %sMB", inst_device_size)
+            logging.warning("Recommended size: %sMB", recommended_size)
+    
+        # Validate the value specified for timezone
+        if not tz_isvalid(timezone):
+            logging.error("Timezone value specified (%s) is not valid", timezone)
+            raise ti_utils.InstallationError
+    
+        # Compute the time to set here.  It will be set after the rtc
+        # command is run, if on x86.
+        install_time = datetime.datetime.now() + install_profile.system.time_offset
+        
+        if platform.processor() == "i386":
+            #
+            # At this time, the /usr/sbin/rtc command does not work in alternate
+            # root.  It hard codes to use /etc/rtc_config.
+            # Therefore, we set the value for rtc_config in the live environment
+            # so it will get copied over to the alternate root.
+            #
+            exec_cmd([RTC_CMD, "-z", timezone], "set timezone")
+            exec_cmd([RTC_CMD, "-c"], "set timezone")
+    
         #
-        exec_cmd([RTC_CMD, "-z", timezone], "set timezone")
-        exec_cmd([RTC_CMD, "-c"], "set timezone")
-
-    #
-    # Set the system time to the time specified by the user
-    # The value to set the time to is computed before the "rtc" commands.
-    # This is required because rtc will mess up the computation of the
-    # time to set.  The rtc command must be run before the command
-    # to set time.  Otherwise, the time that we set will be overwritten
-    # after running /usr/sbin/rtc.
-    #
-    cmd = ["/usr/bin/date", install_time.strftime("%m%d%H%M%y")]
-    exec_cmd(cmd, "set system time")
-
-    time_change_event.set()
+        # Set the system time to the time specified by the user
+        # The value to set the time to is computed before the "rtc" commands.
+        # This is required because rtc will mess up the computation of the
+        # time to set.  The rtc command must be run before the command
+        # to set time.  Otherwise, the time that we set will be overwritten
+        # after running /usr/sbin/rtc.
+        #
+        cmd = ["/usr/bin/date", install_time.strftime("%m%d%H%M%y")]
+        exec_cmd(cmd, "set system time")
+    finally:
+        # Must signal to the main thread to 'wake' whether
+        # the prior lines have succeeded or failed
+        time_change_event.set()
     
     global INSTALL_STATUS
     INSTALL_STATUS = InstallStatus(screen, update_status_func, quit_event)
@@ -626,7 +629,7 @@
     # Run the install-finish script
     cmd = [INSTALL_FINISH_PROG, "-B", INSTALLED_ROOT_DIR, "-R", root_pass,
            "-n", ureal_name, "-l", ulogin, "-p", upass, "-G", ICT_USER_GID,
-           "-U", ICT_USER_UID]
+           "-U", ICT_USER_UID, "-I", "TEXT"]
     if (install_profile.nic.type == NetworkInfo.NONE):
         cmd.append("-N")
     
--- a/usr/src/lib/libict_pymod/ict.py	Wed Jan 05 13:37:29 2011 -0800
+++ b/usr/src/lib/libict_pymod/ict.py	Fri Jan 07 14:58:42 2011 -0800
@@ -19,7 +19,7 @@
 #
 # CDDL HEADER END
 #
-# Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
 #
 '''Install Completion Tasks (ICT)
 
@@ -188,11 +188,11 @@
 ICT_GENERATE_SC_PROFILE_FAILED,
 ICT_SETUP_RBAC_FAILED,
 ICT_SETUP_SUDO_FAILED
-) = range(200,255)
+) = range(200, 255)
 
 # Global variables
 DEBUGLVL = LS_DBGLVL_ERR
-CUR_ICT_FRAME = None  # frame info for debugging and tracing
+CUR_ICT_FRAME = None # frame info for debugging and tracing
 MENU_LST_DEFAULT_TITLE = "Oracle Solaris"
 
 
@@ -1555,6 +1555,13 @@
         _register_task(inspect.currentframe())
         return_status = 0
         for pkg in pkg_list:
+            # check to see if the package exists if not, go to next one
+            check = 'pkg -R %s info %s 2>&1' % (self.basedir, pkg)
+            status, cmdout = _cmd_out(check)
+            if status != 0:
+                _dbg_msg("'%s' is not installed - skipping" % pkg)
+                continue
+
             cmd = 'pkg -R %s uninstall -q --no-index %s 2>&1' % \
                 (self.basedir, pkg)
             status, cmdout = _cmd_out(cmd)
--- a/usr/src/lib/liborchestrator/perform_slim_install.c	Wed Jan 05 13:37:29 2011 -0800
+++ b/usr/src/lib/liborchestrator/perform_slim_install.c	Fri Jan 07 14:58:42 2011 -0800
@@ -19,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
  */
 
 #include <fcntl.h>
@@ -2362,11 +2362,13 @@
 	char *fixed_rpasswd = NULL;
 	char *fixed_uname = NULL;
 	char *fixed_upasswd = NULL;
-
+	char *source  = "LIVE";
 	if (target == NULL) {
 		return (OM_SUCCESS);
 	}
-
+	if (om_is_automated_installation()) {
+		source = "AI";
+	}
 	/*
 	 * It is possible that the username, and passwords could
 	 * contain a single quote. Invoking ict_escape will prepare
@@ -2391,9 +2393,9 @@
 	om_log_print("Running install-finish script\n");
 	(void) snprintf(cmd, sizeof (cmd),
 	    "%s -B '%s' -R '%s' -n '%s' -l '%s' -p '%s' "
-	    "-G '%d' -U '%d'",
+	    "-G '%d' -U '%d' -I '%s'",
 	    tool, target, fixed_rpasswd, fixed_uname, lname,
-	    fixed_upasswd, ICT_USER_GID, ICT_USER_UID);
+	    fixed_upasswd, ICT_USER_GID, ICT_USER_UID, source);
 
 	free(fixed_rpasswd);
 	free(fixed_uname);
--- a/usr/src/pkg/manifests/system-install-text-install.mf	Wed Jan 05 13:37:29 2011 -0800
+++ b/usr/src/pkg/manifests/system-install-text-install.mf	Fri Jan 07 14:58:42 2011 -0800
@@ -19,7 +19,7 @@
 # CDDL HEADER END
 #
 #
-# Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
 #
 
 set name=pkg.fmri value=pkg:/system/install/text-install@$(PKGVERS)
@@ -28,6 +28,7 @@
 set name=info.classification value="org.opensolaris.category.2008:System/Administration and Configuration"
 set name=variant.arch value=$(ARCH)
 set name=variant.opensolaris.zone value=global
+depend fmri=system/install/locale type=require
 dir path=lib
 dir path=lib/svc
 dir path=lib/svc/manifest group=sys