21 |
21 |
22 # |
22 # |
23 # Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved. |
23 # Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved. |
24 # |
24 # |
25 |
25 |
26 # |
|
27 # Only change PATH if you give full consideration to GNU or other variants |
|
28 # of common commands having different arguments and output. Setting PATH is |
|
29 # and not using the full path to executables provides a performance improvement |
|
30 # by using the ksh builtin equivalent of many common commands. |
|
31 # |
|
32 export PATH=/usr/bin:/usr/sbin |
|
33 unset LD_LIBRARY_PATH |
26 unset LD_LIBRARY_PATH |
|
27 PATH=/usr/bin:/usr/sbin |
|
28 export PATH |
34 |
29 |
35 . /usr/lib/brand/shared/common.ksh |
30 . /usr/lib/brand/shared/common.ksh |
36 |
31 |
37 PROP_PARENT="org.opensolaris.libbe:parentbe" |
32 PROP_PARENT="org.opensolaris.libbe:parentbe" |
38 PROP_ACTIVE="org.opensolaris.libbe:active" |
33 PROP_ACTIVE="org.opensolaris.libbe:active" |
39 PROP_BE_HANDLE="com.oracle.libbe:nbe_handle" |
|
40 |
34 |
41 f_incompat_options=$(gettext "cannot specify both %s and %s options") |
35 f_incompat_options=$(gettext "cannot specify both %s and %s options") |
42 f_sanity_detail=$(gettext "Missing %s at %s") |
36 f_sanity_detail=$(gettext "Missing %s at %s") |
43 f_sanity_sparse=$(gettext "Is this a sparse zone image? The image must be whole-root.") |
37 f_sanity_sparse=$(gettext "Is this a sparse zone image? The image must be whole-root.") |
44 sanity_ok=$(gettext " Sanity Check: Passed. Looks like a Solaris system.") |
38 sanity_ok=$(gettext " Sanity Check: Passed. Looks like a Solaris system.") |
45 sanity_fail=$(gettext " Sanity Check: FAILED (see log for details).") |
39 sanity_fail=$(gettext " Sanity Check: FAILED (see log for details).") |
46 sanity_fail_vers=$(gettext " Sanity Check: the Solaris image (release %s) is not an OpenSolaris image and cannot be installed in this type of branded zone.") |
40 sanity_fail_vers=$(gettext " Sanity Check: the Solaris image (release %s) is not an OpenSolaris image and cannot be installed in this type of branded zone.") |
47 install_fail=$(gettext " Result: *** Installation FAILED ***") |
41 install_fail=$(gettext " Result: *** Installation FAILED ***") |
48 f_zfs_in_root=$(gettext "Installing a zone inside of the root pool's 'ROOT' dataset is unsupported.") |
42 f_zfs_in_root=$(gettext "Installing a zone inside of the root pool's 'ROOT' dataset is unsupported.") |
|
43 f_zfs_create=$(gettext "Unable to create the zone's ZFS dataset.") |
49 f_root_create=$(gettext "Unable to create the zone's ZFS dataset mountpoint.") |
44 f_root_create=$(gettext "Unable to create the zone's ZFS dataset mountpoint.") |
50 f_no_gzbe=$(gettext "unable to determine global zone boot environment.") |
45 f_no_gzbe=$(gettext "unable to determine global zone boot environment.") |
|
46 f_no_ds=$(gettext "the zonepath must be a ZFS dataset.\nThe parent directory of the zonepath must be a ZFS dataset so that the\nzonepath ZFS dataset can be created properly.") |
51 f_multiple_ds=$(gettext "multiple active datasets.") |
47 f_multiple_ds=$(gettext "multiple active datasets.") |
52 f_no_active_ds=$(gettext "no active dataset.") |
48 f_no_active_ds=$(gettext "no active dataset.") |
53 f_zfs_unmount=$(gettext "Unable to unmount the zone's root ZFS dataset (%s).\nIs there a global zone process inside the zone root?\nThe current zone boot environment will remain mounted.\n") |
49 f_zfs_unmount=$(gettext "Unable to unmount the zone's root ZFS dataset (%s).\nIs there a global zone process inside the zone root?\nThe current zone boot environment will remain mounted.\n") |
54 f_zfs_mount=$(gettext "Unable to mount the zone's ZFS dataset.") |
50 f_zfs_mount=$(gettext "Unable to mount the zone's ZFS dataset.") |
55 |
51 |
133 fi |
144 fi |
134 |
145 |
135 vlog "$sanity_ok" |
146 vlog "$sanity_ok" |
136 } |
147 } |
137 |
148 |
138 function get_current_gzbe { |
149 get_current_gzbe() { |
139 # |
150 # |
140 # If there is no alternate root (normal case) then set the |
151 # If there is no alternate root (normal case) then set the |
141 # global zone boot environment by finding the boot environment |
152 # global zone boot environment by finding the boot environment |
142 # that is active now. |
153 # that is active now. |
143 # If a zone exists in a boot environment mounted on an alternate root, |
154 # If a zone exists in a boot environment mounted on an alternate root, |
144 # then find the boot environment where the alternate root is mounted. |
155 # then find the boot environment where the alternate root is mounted. |
145 # |
156 # |
146 CURRENT_GZBE=$(beadm list -H | nawk -v alt=$ALTROOT -F\; '{ |
157 if [ -x /usr/sbin/beadm ]; then |
147 if (length(alt) == 0) { |
158 CURRENT_GZBE=`/usr/sbin/beadm list -H | /usr/bin/nawk \ |
148 # Field 3 is the BE status. 'N' is the active BE. |
159 -v alt=$ALTROOT -F\; '{ |
149 if ($3 !~ "N") |
160 if (length(alt) == 0) { |
150 next |
161 # Field 3 is the BE status. 'N' is the active BE. |
151 } else { |
162 if ($3 !~ "N") |
152 # Field 4 is the BE mountpoint. |
163 next |
153 if ($4 != alt) |
164 } else { |
154 next |
165 # Field 4 is the BE mountpoint. |
|
166 if ($4 != alt) |
|
167 next |
|
168 } |
|
169 # Field 2 is the BE UUID |
|
170 print $2 |
|
171 }'` |
|
172 else |
|
173 # If there is no beadm command then the system doesn't really |
|
174 # support multiple boot environments. We still want zones to |
|
175 # work so simulate the existence of a single boot environment. |
|
176 CURRENT_GZBE="opensolaris" |
|
177 fi |
|
178 |
|
179 if [ -z "$CURRENT_GZBE" ]; then |
|
180 fail_fatal "$f_no_gzbe" |
|
181 fi |
|
182 } |
|
183 |
|
184 # Find the active dataset under the zonepath dataset to mount on zonepath/root. |
|
185 # $1 CURRENT_GZBE |
|
186 # $2 ZONEPATH_DS |
|
187 get_active_ds() { |
|
188 ACTIVE_DS=`/usr/sbin/zfs list -H -r -t filesystem \ |
|
189 -o name,$PROP_PARENT,$PROP_ACTIVE $2/ROOT | \ |
|
190 /usr/bin/nawk -v gzbe=$1 ' { |
|
191 if ($1 ~ /ROOT\/[^\/]+$/ && $2 == gzbe && $3 == "on") { |
|
192 print $1 |
|
193 if (found == 1) |
|
194 exit 1 |
|
195 found = 1 |
155 } |
196 } |
156 # Field 2 is the BE UUID |
197 }'` |
157 print $2 |
198 |
158 }') |
199 if [ $? -ne 0 ]; then |
159 if [ -z "$CURRENT_GZBE" ]; then |
200 fail_fatal "$f_multiple_ds" |
160 return 1 |
201 fi |
161 fi |
202 |
162 return 0 |
203 if [ -z "$ACTIVE_DS" ]; then |
163 } |
204 fail_fatal "$f_no_active_ds" |
164 |
205 fi |
165 # |
206 } |
166 # get_active_be zone |
207 |
167 # |
208 # Check that zone is not in the ROOT dataset. |
168 # Finds the active boot environment for the given zone. |
209 fail_zonepath_in_rootds() { |
169 # |
210 case $1 in |
170 # Arguments: |
211 rpool/ROOT/*) |
171 # |
212 fail_fatal "$f_zfs_in_root" |
172 # zone zone structure initialized with init_zone |
213 break; |
173 # |
214 ;; |
174 # Globals: |
215 *) |
175 # |
216 break; |
176 # CURRENT_GZBE Current global zone boot environment. If not already set, |
217 ;; |
177 # it will be set. |
218 esac |
178 # |
219 } |
179 # Returns: |
220 |
180 # |
221 # |
181 # 0 on success, else 1. |
222 # Make sure the active dataset is mounted for the zone. There are several |
182 # |
223 # cases to consider: |
183 function get_active_be { |
224 # 1) First boot of the zone, nothing is mounted |
184 typeset -n zone=$1 |
225 # 2) Zone is halting, active dataset remains the same. |
185 typeset active_ds= |
226 # 3) Zone is halting, there is a new active dataset to mount. |
186 typeset tab=$(printf "\t") |
227 # |
187 |
228 mount_active_ds() { |
188 [[ -z "$CURRENT_GZBE" ]] && get_current_gzbe |
229 mount -p | cut -d' ' -f3 | egrep -s "^$ZONEPATH/root$" |
189 |
230 if (( $? == 0 )); then |
190 typeset name parent active |
231 # Umount current dataset on the root (it might be an old BE). |
191 zfs list -H -r -d 1 -t filesystem -o name,$PROP_PARENT,$PROP_ACTIVE \ |
232 umount $ZONEPATH/root |
192 ${zone.ROOT_ds} | while IFS=$tab read name parent active ; do |
233 if (( $? != 0 )); then |
193 [[ $parent == "$CURRENT_GZBE" ]] || continue |
234 # The umount failed, leave the old BE mounted. |
194 [[ $active == on ]] || continue |
235 # Warn about gz process preventing umount. |
195 vlog "Found active dataset %s" "$name" |
236 printf "$f_zfs_unmount" "$ZONEPATH/root" |
196 if [[ -n "$active_ds" ]] ; then |
237 return |
197 error "$f_multiple_ds" |
|
198 return 1 |
|
199 fi |
238 fi |
200 active_ds=$name |
239 fi |
|
240 |
|
241 # Mount active dataset on the root. |
|
242 get_current_gzbe |
|
243 get_zonepath_ds $ZONEPATH |
|
244 get_active_ds $CURRENT_GZBE $ZONEPATH_DS |
|
245 |
|
246 mount -F zfs $ACTIVE_DS $ZONEPATH/root || fail_fatal "$f_zfs_mount" |
|
247 } |
|
248 |
|
249 # |
|
250 # Set up ZFS dataset hierarchy for the zone root dataset. |
|
251 # |
|
252 create_active_ds() { |
|
253 get_current_gzbe |
|
254 |
|
255 # |
|
256 # Find the zone's current dataset. This should have been created by |
|
257 # zoneadm. |
|
258 # |
|
259 get_zonepath_ds $zonepath |
|
260 |
|
261 # Check that zone is not in the ROOT dataset. |
|
262 fail_zonepath_in_rootds $ZONEPATH_DS |
|
263 |
|
264 # |
|
265 # From here on, errors should cause the zone to be incomplete. |
|
266 # |
|
267 int_code=$ZONE_SUBPROC_FATAL |
|
268 |
|
269 # |
|
270 # We need to tolerate errors while creating the datasets and making the |
|
271 # mountpoint, since these could already exist from some other BE. |
|
272 # |
|
273 |
|
274 /usr/sbin/zfs list -H -o name $ZONEPATH_DS/ROOT >/dev/null 2>&1 |
|
275 if (( $? != 0 )); then |
|
276 /usr/sbin/zfs create -o mountpoint=legacy \ |
|
277 -o zoned=on $ZONEPATH_DS/ROOT |
|
278 if (( $? != 0 )); then |
|
279 fail_fatal "$f_zfs_create" |
|
280 fi |
|
281 fi |
|
282 |
|
283 BENAME=zbe |
|
284 BENUM=0 |
|
285 # Try 100 different names before giving up. |
|
286 while [ $BENUM -lt 100 ]; do |
|
287 /usr/sbin/zfs create -o $PROP_ACTIVE=on \ |
|
288 -o $PROP_PARENT=$CURRENT_GZBE \ |
|
289 -o canmount=noauto $ZONEPATH_DS/ROOT/$BENAME >/dev/null 2>&1 |
|
290 if (( $? == 0 )); then |
|
291 break |
|
292 fi |
|
293 BENUM=`expr $BENUM + 1` |
|
294 BENAME="zbe-$BENUM" |
201 done |
295 done |
202 if [[ -z $active_ds ]]; then |
296 |
203 error "$f_no_active_ds" |
297 if [ $BENUM -ge 100 ]; then |
204 return 1 |
298 fail_fatal "$f_zfs_create" |
205 fi |
299 fi |
206 |
300 |
207 zone.active_ds=$active_ds |
301 if [ ! -d $ZONEROOT ]; then |
208 } |
302 /usr/bin/mkdir $ZONEROOT |
209 |
303 fi |
210 function set_active_be { |
304 |
211 typeset -n zone="$1" |
305 /usr/sbin/mount -F zfs $ZONEPATH_DS/ROOT/$BENAME $ZONEROOT || \ |
212 typeset be="$2" |
306 fail_incomplete "$f_zfs_mount" |
213 |
|
214 [[ -z "$CURRENT_GZBE" ]] && get_current_gzbe |
|
215 |
|
216 # |
|
217 # Turn off the active property on BE's with the same GZBE |
|
218 # |
|
219 zfs list -H -r -d 1 -t filesystem -o name,$PROP_PARENT,$PROP_ACTIVE \ |
|
220 ${zone.ROOT_ds} | while IFS=$tab read name parent active ; do |
|
221 [[ $parent == "$CURRENT_GZBE" ]] || continue |
|
222 [[ $active == on ]] || continue |
|
223 [[ $name == "${zone.ROOT_ds}/$be" ]] && continue |
|
224 vlog "Deactivating active dataset %s" "$name" |
|
225 zfs set $PROP_ACTIVE=off "$name" || return 1 |
|
226 done |
|
227 |
|
228 zone.active_ds="${zone.ROOT_ds}/$be" |
|
229 |
|
230 zfs set "$PROP_PARENT=$CURRENT_GZBE" ${zone.active_ds} \ |
|
231 || return 1 |
|
232 zfs set "$PROP_ACTIVE=on" ${zone.active_ds} || return 1 |
|
233 |
|
234 zfs set "$PROP_BE_HANDLE=on" "${zone.rpool_ds}" || return 1 |
|
235 |
|
236 return 0 |
|
237 } |
307 } |
238 |
308 |
239 # |
309 # |
240 # Run sys-unconfig on the zone. |
310 # Run sys-unconfig on the zone. |
241 # |
311 # |