#!/sbin/sh # # Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved. # . /lib/svc/share/smf_include.sh # # Establish PATH for non-built in commands # export PATH=/sbin:/usr/bin:/usr/sbin # Usage USAGE="Usage: $0 start" # name of profile generated by System Configuration Interactive (SCI) tool SCIT_PROFILE="sc_profile.xml" # configuration properties PROP_CONFIGURE="sysconfig/configure" PROP_INTERACTIVE_CONFIG="sysconfig/interactive_config" PROP_CONFIG_GROUPS="sysconfig/config_groups" PROP_CONFIG_DIR="sysconfig/config_dir" # default value for unconfigured properties SMF_UNCONFIGURED_VALUE="" SVCADM="/usr/sbin/svcadm" SVCCFG="/usr/sbin/svccfg" SVCPROP="/usr/bin/svcprop" # # Binary tested for determining if we are in ROZR zone booted in ready-only # mode. # ROZR_TEST_BINARY="/sbin/sh" ROZR_ERR_MSG="\nDetected ROZR zone booted in read-only mode. System \ Configuration not permitted.\nPlease refer to mwac(5) man page \ for additional information.\n" # # get_smf_prop() # # Description: # Retrieve value of SMF property. # For 'astring' type of property, take care of removing quoting backslashes, # since according to svcprop(1) man page, shell metacharacters # (';', '&', '(', ')', '|', '^', '<', '>', newline, space, tab, backslash, # '"', single-quote, '`') are quoted by backslashes (\). # # Parameters: # $1 - SMF property name # # Returns: # 0 - property was configured in SC manifest # 1 - property was not configured in SC manifest # get_smf_prop() { typeset prop_name="$1" typeset prop_value typeset prop_type # # If property is not set for service instance (which means it was not # defined in SC manifest), return with 'unconfigured' value. # $SVCPROP -Cq -p "$prop_name" $SMF_FMRI if (( $? != 0 )) ; then print -u1 $SMF_UNCONFIGURED_VALUE return 1 fi # retrieve property. prop_value=$($SVCPROP -p "$prop_name" $SMF_FMRI) if (( $? != 0 )) ; then print -u2 "Failed to obtain value of <$prop_name> property" \ "which is suspicious, defaulting to" \ "<$SMF_UNCONFIGURED_VALUE>." print -u1 $SMF_UNCONFIGURED_VALUE return 1 fi # for 'astring' type, remove backslashes from quoted metacharacters prop_type=$($SVCCFG -s $SMF_FMRI listprop "$prop_name" | nawk '{ print $2 }') if [[ "$prop_type" == "astring" ]] ; then prop_value=$(print "$prop_value" | sed -e 's/\\\(.\)/\1/g') if (( $? != 0 )) ; then print -u2 "Failed when trying to remove '\' from" \ "<$prop_name> property, defaulting to" \ "<$SMF_UNCONFIGURED_VALUE>." print -u1 $SMF_UNCONFIGURED_VALUE return 1 fi # # Since according to svcprop(1) man page empty ASCII string # value is presented as a pair of double quotes (""), we need # to check for this combination and replace it # with empty string. # [[ "$prop_value" == '""' ]] && prop_value="" fi print -u1 "$prop_value" return 0 } # # set_terminal_type() # # Description: # If TERM variable is not defined, set it to: # * "sun" if connected to SPARC via keyboard/monitor, # * "sun-color" if connected to X86 via keyboard/monitor, # * "xterm" otherwise. # set_terminal_type() { [[ -n "$TERM" ]] && return # start with xterm as a default value TERM=xterm # call into getconsole.py to get the type of console /usr/bin/python2.7 -c \ "from solaris_install.getconsole import main; main()" \ > /dev/null 2>&1 ret=$? # main() will return 1 if we're runnng on a physical console if [[ $ret == 1 ]]; then arch=$(uname -p) if [[ "$arch" == "sparc" ]]; then TERM=sun else TERM=sun-color fi fi print -u1 " Setting terminal type to $TERM." export TERM } # # run_sci_tool() # # Description: # Invokes System Configuration Interactive tool. # Aborts with SMF_EXIT_ERR_FATAL in case of fatal failure. # run_sci_tool() { print -u1 " Interactive configuration requested," \ "bringing up System Configuration Interactive tool." if [[ -z $(which sysconfig 2>/dev/null) ]] ; then print -u1 " SCI tool not found, skipping interactive" \ "configuration." return fi # # First make sure terminal type is configured. That's required by curses # module which SCI tool consumes. # set_terminal_type # extract the groupings to configure sci_screens=$(get_smf_prop $PROP_CONFIG_GROUPS) if [[ -z "$sci_screens" ]] ; then print -u1 " There are no SCI screens to be displayed," \ "skipping interactive configuration." return fi print -u1 " SCI screens to be displayed: <$sci_screens>" # Groupings are stored in the smf property/group with spaces # Convert them to replace spaces with commas sci_screens=`echo $sci_screens | sed 's/ /,/g'` # set the output path for create-profile config_dir=$(get_smf_prop $PROP_CONFIG_DIR) if [[ -z "$config_dir" ]] ; then # create a directory in /etc/svc/profile/sysconfig # based on the current timestamp timestamp=`/usr/bin/date '+%Y%m%d-%H%M%S'` config_dir="/etc/svc/profile/sysconfig/sysconfig-$timestamp" print -u1 " 'config_dir' property not set in config" \ "profile. Creating a new directory at $config_dir" mkdir -p $config_dir chmod 755 $config_dir $SVCCFG -s $SMF_FMRI setprop $PROP_CONFIG_DIR = astring: "$config_dir" if (( $? == 0 )); then $SVCADM refresh $SMF_FMRI else print -u2 "Failed to set the $PROP_CONFIG_DIR" \ "property" | smf_console # clear all administrative customizations for this # service $SVCCFG -s $SMF_FMRI delcust $SVCCFG -s $SMF_FMRI refresh exit $SMF_EXIT_ERR_FATAL fi fi sysconfig create-profile -g $sci_screens -o $config_dir \ < /dev/console > /dev/console 2>&1 typeset -i ret=$? # if SCI tool failed to create SC profile, abort if [[ $ret != 0 ]] ; then print -u1 " SCI tool did not create SC profile," \ "skipping the rest of interactive configuration." \ "Interactive configuration will resume on next" \ "boot." | smf_console # exit without clearing the administrative # customizations so the sci_tool will run upon reboot exit $SMF_EXIT_ERR_FATAL fi } # # apply_profile() # # Description: # Applies SMF profile generated by the SCI tool or as passed # in to sysconfig # # NOTE: # Because svccfg apply and import send the refresh through to the # restarter(s) so that the refresh method is ran after the snapshot # is taken, the refresh in these cases becomes asynchronous. This # causes a problem in that the apply here is for services outside our # control and are offline. So they will not refresh immediately and # therefor there is a window that is open for svcprop to not get incoming # properties. # # When doing a svccfg apply (or import) to an SMF repository that # currently does not have a restarter monitoring events from updates # to that repository, svccfg simply takes the snapshot. In the case here # all services that the profile affects should be offline due to the # dependencies and will come back only after the apply. So we need to # just simply apply the profiles and take the snapshots without worry # of executing refresh methods. Setting the SMF_FMRI to the early # manifest-import service will trick svccfg into taking the running # snapshots itself without a push through to startd for the event. # # THIS IS A HACK - to resolve this issue until after synchronous refresh # can be implemented or possibly an option to svccfg to simply take the # snapshots without the need for a refresh method execution on apply or # import. # # DO NOT PROPAGATE THIS CODE BEYOND THIS CHANGE! # SEE BUG-ID : 7044661 # apply_profile() { config_dir=$(get_smf_prop $PROP_CONFIG_DIR) # set SMF_FMRI to EMI PRE_FMRI=$SMF_FMRI SMF_FMRI="svc:/system/early-manifest-import:default" # Apply the profile to the admin layer $SVCCFG apply $config_dir typeset -i ret=$? # restore the proper SMF_FRMI value SMF_FMRI=$PRE_FMRI if (( $ret != 0 )); then print -u1 " svccfg apply failed to apply the system " \ "configuration profile." | smf_console # clear all administrative customizations for this service $SVCCFG -s $SMF_FMRI delcust $SVCCFG -s $SMF_FMRI refresh exit $SMF_EXIT_ERR_FATAL fi } # # configure_system() # # Description: # Takes care of generic System Configuration tasks: # - in case of interactive configuration scenario, invokes # System Configuration Interactive tool # - applies generated System Configuration profile # configure_system() { # Check if system configuration should be carried out enable_configuration=$(get_smf_prop $PROP_CONFIGURE) if [[ "$enable_configuration" == "true" ]]; then # # Running configuration process is not permitted in ROZR # non-global zone booted in read-only mode. # if [[ ! -w "$ROZR_TEST_BINARY" ]] ; then print -u1 "$ROZR_ERR_MSG" | smf_console # clear all administrative customizations for this # service $SVCCFG -s $SMF_FMRI delcust $SVCCFG -s $SMF_FMRI refresh exit $SMF_EXIT_ERR_FATAL fi # # Check if System Configuration Interactive tool should be # invoked to carry out interactive system configuration. # interactive_config=$(get_smf_prop $PROP_INTERACTIVE_CONFIG) if [[ "$interactive_config" == "true" ]]; then run_sci_tool fi # Apply the new SMF profile apply_profile # clear all administrative customizations for this service $SVCCFG -s $SMF_FMRI delcust $SVCCFG -s $SMF_FMRI refresh print -u1 "System successfully configured." fi } ## Main ## case "$1" in 'start') configure_system ;; *) print -u2 "$USAGE" exit $SMF_EXIT_ERR_FATAL ;; esac exit $SMF_EXIT_OK