1 #!/bin/ksh -p
2 #
3 # CDDL HEADER START
4 #
5 # The contents of this file are subject to the terms of the
6 # Common Development and Distribution License (the "License").
7 # You may not use this file except in compliance with the License.
8 #
9 # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 # or http://www.opensolaris.org/os/licensing.
11 # See the License for the specific language governing permissions
12 # and limitations under the License.
13 #
14 # When distributing Covered Code, include this CDDL HEADER in each
15 # file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 # If applicable, add the following below this CDDL HEADER, with the
17 # fields enclosed by brackets "[]" replaced with your own identifying
18 # information: Portions Copyright [yyyy] [name of copyright owner]
19 #
20 # CDDL HEADER END
21 #
22 # Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 # Use is subject to license terms.
24 #
25
26 #
27 # image_install is used when installing a zone in a 'p2v' scenario. In
28 # this case the zone install hook will branch off to this script which
29 # is responsible for setting up the physical system image in the zonepath
30 # and performing the various modifications necessary to enable a physical
31 # system image to run inside a zone. This script sets up the image in the
32 # zonepath then calls the p2v script to modify the image to run in a zone.
33 #
34
35 . /usr/lib/brand/ipkg/common.ksh
36
37 m_usage=$(gettext "\n install {-a archive|-d path} {-p|-u} [-s|-v]")
38 install_log=$(gettext " Log File: %s")
39
40 p2ving=$(gettext "Postprocessing: This may take a while...")
41 p2v_prog=$(gettext " Postprocess: ")
42 p2v_done=$(gettext " Result: Postprocessing complete.")
43 p2v_fail=$(gettext " Result: Postprocessing failed.")
44 m_postnote3=$(gettext " Make any other adjustments, such as disabling SMF services\n that are no longer needed.")
45
46 media_missing=\
47 $(gettext "%s: you must specify an installation source using '-a' or '-d'.")
48 cfgchoice_missing=\
49 $(gettext "you must specify -u (sys-unconfig) or -p (preserve identity).")
50
51 # Clean up on interrupt
52 trap_cleanup()
53 {
54 msg=$(gettext "Installation cancelled due to interrupt.")
55 log "$msg"
56
57 trap_exit
58 }
59
60 # If the install failed then clean up the ZFS datasets we created.
61 trap_exit()
62 {
63 # umount any mounted file systems
64 [[ -n "$fstmpfile" ]] && umnt_fs
65
66 if (( $zone_is_mounted != 0 )); then
67 error "$v_unmount"
68 zoneadm -z $ZONENAME unmount
69 zone_is_mounted=0
70 fi
71
72 if (( $EXIT_CODE != $ZONE_SUBPROC_OK )); then
73 /usr/lib/brand/ipkg/uninstall $ZONENAME $ZONEPATH -F
74 fi
75
76 exit $EXIT_CODE
77 }
78
79 #
80 # The main body of the script starts here.
81 #
82 # This script should never be called directly by a user but rather should
83 # only be called by pkgcreatezone to install an OpenSolaris system image into
84 # a zone.
85 #
86
87 #
88 # Exit code to return if install is interrupted or exit code is otherwise
89 # unspecified.
90 #
91 EXIT_CODE=$ZONE_SUBPROC_USAGE
92
93 zone_is_mounted=0
94 trap trap_cleanup INT
95 trap trap_exit EXIT
96
97 # If we weren't passed at least two arguments, exit now.
98 (( $# < 2 )) && exit $ZONE_SUBPROC_USAGE
99
100 ZONENAME="$1"
101 ZONEPATH="$2"
102 # XXX shared/common script currently uses lower case zonename & zonepath
103 zonename="$ZONENAME"
104 zonepath="$ZONEPATH"
105
106 ZONEROOT="$ZONEPATH/root"
107
108 shift; shift # remove zonename and zonepath from arguments array
109
110 unset inst_type
111 unset msg
112 unset silent_mode
113 unset verbose_mode
114
115 #
116 # It is worth noting here that we require the end user to pick one of
117 # -u (sys-unconfig) or -p (preserve config). This is because we can't
118 # really know in advance which option makes a better default. Forcing
119 # the user to pick one or the other means that they will consider their
120 # choice and hopefully not be surprised or disappointed with the result.
121 #
122 unset unconfig_zone
123 unset preserve_zone
124
125 while getopts "a:d:psuv" opt
126 do
127 case "$opt" in
128 a)
129 if [[ -n "$inst_type" ]]; then
130 fatal "$both_kinds" "zoneadm install"
131 fi
132 inst_type="archive"
133 install_media="$OPTARG"
134 ;;
135 d)
136 if [[ -n "$inst_type" ]]; then
137 fatal "$both_kinds" "zoneadm install"
138 fi
139 inst_type="directory"
140 install_media="$OPTARG"
141 ;;
142 p) preserve_zone="-p";;
143 s) silent_mode=1;;
144 u) unconfig_zone="-u";;
145 v) verbose_mode="-v";;
146 *) exit $ZONE_SUBPROC_USAGE;;
147 esac
148 done
149 shift OPTIND-1
150
151 # The install can't be both verbose AND silent...
152 [[ -n $silent_mode && -n $verbose_mode ]] && \
153 fatal "$f_incompat_options" "-s" "-v"
154
155 [[ -z $install_media ]] && fatal "$media_missing" "zoneadm install"
156
157 # The install can't both preserve and unconfigure
158 [[ -n $unconfig_zone && -n $preserve_zone ]] && \
159 fatal "$f_incompat_options" "-u" "-p"
160
161 # Must pick one or the other.
162 [[ -z $unconfig_zone && -z $preserve_zone ]] && fail_usage "$cfgchoice_missing"
163
164 LOGFILE=$(/usr/bin/mktemp -t -p /var/tmp $ZONENAME.install_log.XXXXXX)
165 [[ -z "$LOGFILE" ]] && fatal "$e_tmpfile"
166 exec 2>>"$LOGFILE"
167 log "$install_log" "$LOGFILE"
168
169 vlog "Starting pre-installation tasks."
170
171 #
172 # From here on out, an unspecified exit or interrupt should exit with
173 # ZONE_SUBPROC_NOTCOMPLETE, meaning a user will need to do an uninstall before
174 # attempting another install, as we've modified the directories we were going
175 # to install to in some way.
176 #
177 EXIT_CODE=$ZONE_SUBPROC_NOTCOMPLETE
178
179 # ZONEROOT was created by our caller (pkgcreatezone)
180
181 vlog "Installation started for zone \"$ZONENAME\""
182 install_image "$inst_type" "$install_media"
183
184 #
185 # Run p2v.
186 #
187 # Getting the output to the right places is a little tricky because what
188 # we want is for p2v to output in the same way the installer does: verbose
189 # messages to the log file always, and verbose messages printed to the
190 # user if the user passes -v. This rules out simple redirection. And
191 # we can't use tee or other tricks because they cause us to lose the
192 # return value from the p2v script due to the way shell pipelines work.
193 #
194 # The simplest way to do this seems to be to hand off the management of
195 # the log file to the p2v script. So we run p2v with -l to tell it where
196 # to find the log file and then reopen the log (O_APPEND) when p2v is done.
197 #
198 log "$p2ving"
199 vlog "running: p2v $verbose_mode $unconfig_zone $ZONENAME $ZONEPATH"
200 /usr/lib/brand/ipkg/p2v -l "$LOGFILE" $verbose_mode $unconfig_zone $ZONENAME \
201 $ZONEPATH
202 p2v_result=$?
203 exec 2>>$LOGFILE
204
205 if (( $p2v_result != 0 )); then
206 log "$p2v_fail"
207 log ""
208 log "$install_fail"
209 log "$install_log" "$LOGFILE"
210 exit $ZONE_SUBPROC_FATAL
211 fi
212 vlog "$p2v_done"
213
214 zone_is_mounted=1
215 zoneadm -z $ZONENAME mount -f || fatal "$e_badmount"
216
217 safe_copy $LOGFILE $ZONEPATH/lu/a/var/log/$ZONENAME.install$$.log
218
219 zoneadm -z $ZONENAME unmount || fatal "$e_badunmount"
220 zone_is_mounted=0
221
222 trap - EXIT
223 rm -f $LOGFILE
224
225 # Mount active dataset on the root.
226 is_brand_labeled
227 (( $? == 0 )) && mount_active_ds
228
229 log ""
230 log "$m_complete" ${SECONDS}
231 printf "$install_log\n" "$ZONEROOT/var/log/$ZONENAME.install$$.log"
232 printf "$m_postnote\n"
233 printf "$m_postnote2\n"
234 printf "$m_postnote3\n"
235
236 exit $ZONE_SUBPROC_OK