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.
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.
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]
22 # Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
25 # NOTE: this script runs in the global zone and touches the non-global
26 # zone, so care should be taken to validate any modifications so that they
29 .
/usr
/lib
/brand
/solaris10
/common.ksh
37 echo "$0 [-s] [-m msgprefix] [-u] [-v] [-b patchid]* zonename" >&2
41 # Clean up on interrupt
44 msg
=$
(gettext "Postprocessing cancelled due to interrupt.")
47 if (( $zone_is_running != 0 )); then
48 error
"$e_shutdown" "$ZONENAME"
49 /usr
/sbin
/zoneadm
-z $ZONENAME halt
53 # Delete temporary files created during the hollow package removal
56 rm -f $hollow_pkgs $hollow_file_list $hollow_dir_list
62 # Disable any existing live-upgrade configuration.
63 # We have already called safe_dir to validate the etc/lu directory.
67 ludir
=$ZONEROOT/etc
/lu
69 [[ ! -d $ludir ]] && return
72 safe_rm etc
/lu
/.BE_CONFIG
73 safe_rm etc
/lu
/.CURR_VARS
74 safe_rm etc
/lu
/ludb.
local.xml
75 for i
in $ludir/ICF
* $ludir/vtoc
* $ludir/GRUB
*
83 # For an exclusive stack zone, fix up the network configuration files.
84 # We need to do this even if unconfiguring the zone so sys-unconfig works
89 [[ "$STACK_TYPE" == "shared" ]] && return
91 NETIF_CNT
=$
(/usr
/bin
/ls $ZONEROOT/etc
/hostname.
* 2>/dev
/null | \
93 if (( $NETIF_CNT != 1 )); then
98 NET
=$
(LC_ALL
=C
/usr
/sbin
/zonecfg
-z $ZONENAME info net
)
99 if (( $?
!= 0 )); then
100 error
"$e_badinfo" "net"
104 NETIF
=$
(echo $NET |
/usr
/bin
/nawk
'{
105 for (i = 1; i < NF; i++) {
106 if ($i == "physical:") {
107 if (length(net) == 0) {
120 if [[ -z "$NETIF" ]]; then
125 OLD_HOSTNET
=$
(/usr
/bin
/ls $ZONEROOT/etc
/hostname.
*)
126 if [[ "$OLD_HOSTNET" != "$ZONEROOT/etc/hostname.$NETIF" ]]; then
127 safe_move
$OLD_HOSTNET $ZONEROOT/etc
/hostname.
$NETIF
132 # Disable all of the shares since the zone cannot be an NFS server.
133 # Note that we disable the various instances of the svc:/network/shares/group
134 # SMF service in the fix_smf function.
138 zonedfs
=$ZONEROOT/etc
/dfs
140 [[ ! -d $zonedfs ]] && return
142 if [[ -h $zonedfs/dfstab ||
! -f $zonedfs/dfstab
]]; then
143 error
"$e_badfile" "/etc/dfs/dfstab"
148 if [[ $?
== 1 ||
-z "$tmpfile" ]]; then
154 if (substr($1, 0, 1) == "#") {
163 printf("# Modified by p2v ")
164 system("/usr/bin/date")
168 }' $zonedfs/dfstab
>>$tmpfile
170 if (( $?
== 0 )); then
171 if [[ ! -f $zonedfs/dfstab.pre_p2v
]]; then
172 safe_copy
$zonedfs/dfstab
$zonedfs/dfstab.pre_p2v
174 safe_copy
$tmpfile $zonedfs/dfstab
175 chown root
:sys
$zonedfs/dfstab || \
176 fail_fatal
"$f_chown" "$zonedfs/dfstab"
177 chmod 644 $zonedfs/dfstab || \
178 fail_fatal
"$f_chmod" "$zonedfs/dfstab"
180 /usr
/bin
/rm -f $tmpfile
184 # Comment out most of the old mounts since they are either unneeded or
185 # likely incorrect within a zone. Specific mounts can be manually
186 # reenabled if the corresponding device is added to the zone.
190 if [[ -h $ZONEROOT/etc
/vfstab ||
! -f $ZONEROOT/etc
/vfstab
]]; then
191 error
"$e_badfile" "/etc/vfstab"
196 if [[ $?
== 1 ||
-z "$tmpfile" ]]; then
202 if (substr($1, 0, 1) == "#") {
204 } else if ($1 == "fd" || $1 == "/proc" || $1 == "swap" ||
205 $1 == "ctfs" || $1 == "objfs" || $1 == "sharefs" ||
206 $4 == "nfs" || $4 == "lofs") {
215 printf("# Modified by p2v ")
216 system("/usr/bin/date")
220 }' $ZONEROOT/etc
/vfstab
>>$tmpfile
222 if (( $?
== 0 )); then
223 if [[ ! -f $ZONEROOT/etc
/vfstab.pre_p2v
]]; then
224 safe_copy
$ZONEROOT/etc
/vfstab \
225 $ZONEROOT/etc
/vfstab.pre_p2v
227 safe_copy
$tmpfile $ZONEROOT/etc
/vfstab
228 chown root
:sys
$ZONEROOT/etc
/vfstab || \
229 fail_fatal
"$f_chown" "$ZONEROOT/etc/vfstab"
230 chmod 644 $ZONEROOT/etc
/vfstab || \
231 fail_fatal
"$f_chmod" "$ZONEROOT/etc/vfstab"
233 /usr
/bin
/rm -f $tmpfile
237 # Collect the data needed to delete SMF services. Since we're p2v-ing a
238 # physical image there are SMF services which must be deleted.
243 # Start by getting the svc manifests that are delivered by hollow
244 # pkgs then use 'svccfg inventory' to get the names of the svcs
245 # delivered by those manifests. The svc names are saved into a
249 SMFTMPFILE
=$
(mktemp
-t smf.XXXXXX
)
250 if [[ $?
== 1 ||
-z "$SMFTMPFILE" ]]; then
255 for i
in $ZONEROOT/var
/sadm
/pkg
/*
257 pkg
=$
(/usr
/bin
/basename $i)
258 [[ ! -f $ZONEROOT/var
/sadm
/pkg
/$pkg/save
/pspool
/$pkg/pkgmap
]] \
261 /usr
/bin
/egrep -s "SUNW_PKG_HOLLOW=true" \
262 $ZONEROOT/var
/sadm
/pkg
/$pkg/pkginfo ||
continue
264 for j
in $
(/usr
/bin
/nawk
'{if ($2 == "f" &&
265 substr($4, 1, 17) == "var/svc/manifest/") print $4}' \
266 $ZONEROOT/var
/sadm
/pkg
/$pkg/save
/pspool
/$pkg/pkgmap
)
268 svcs
=$
(SVCCFG_NOVALIDATE
=1 \
269 SVCCFG_REPOSITORY
=$ZONEROOT/etc
/svc
/repository.db \
270 /usr
/sbin
/svccfg inventory
$ZONEROOT/$j)
273 echo $k /$j >> $SMFTMPFILE
280 # Delete or disable SMF services.
281 # Zone is booted to milestone=none when this function is called.
282 # Use the SMF data collected by fix_smf_pre_uoa() to delete the services.
287 # Zone was already booted to milestone=none, wait until SMF door exists.
289 for i
in 0 1 2 3 4 5 6 7 8 9
291 [[ -r $ZONEROOT/etc
/svc
/volatile
/repository_door
]] && break
295 if [[ $i -eq 9 && ! -r $ZONEROOT/etc
/svc
/volatile
/repository_door
]];
298 # The zone never booted, something is wrong.
302 /usr
/bin
/rm -f $SMFTMPFILE
306 insttmpfile
=$
(mktemp
-t instsmf.XXXXXX
)
307 if [[ $?
== 1 ||
-z "$insttmpfile" ]]; then
309 /usr
/bin
/rm -f $SMFTMPFILE
313 vlog
"$v_rmhollowsvcs"
317 vlog
"$v_delsvc" "$fmri"
318 echo "/usr/sbin/svccfg delete -f $fmri"
319 echo "/usr/sbin/svccfg delhash -d $mfst"
321 done < $SMFTMPFILE > $ZONEROOT/tmp
/smf_rm
323 /usr
/sbin
/zlogin
-S $ZONENAME /bin
/sh
/tmp
/smf_rm
>/dev
/null
2>&1
325 /usr
/bin
/rm -f $SMFTMPFILE
327 # Get a list of the svcs that now exist in the zone.
328 LANG
=C
/usr
/sbin
/zlogin
-S $ZONENAME /usr
/bin
/svcs
-aH | \
329 /usr
/bin
/nawk
'{print $3}' >>$insttmpfile
331 [[ -n $LOGFILE ]] && \
332 printf "[$(date)] ${MSG_PREFIX}${v_svcsinzone}\n" >&2
333 [[ -n $LOGFILE ]] && cat $insttmpfile >&2
336 # Import ip-interface-management service in S10C, network
337 # loopback service requires ipmgmtd in exclusive stack zones.
339 /usr
/sbin
/zlogin
-S $ZONENAME /usr
/sbin
/svccfg import \
340 $ZONEROOT/var
/svc
/manifest
/network
/network-ipmgmt.xml
343 # Fix network services if shared stack.
345 if [[ "$STACK_TYPE" == "shared" ]]; then
348 NETPHYSDEF
="svc:/network/physical:default"
349 NETPHYSNWAM
="svc:/network/physical:nwam"
351 /usr
/bin
/egrep -s "$NETPHYSDEF" $insttmpfile
352 if (( $?
== 0 )); then
353 vlog
"$v_enblsvc" "$NETPHYSDEF"
354 /usr
/sbin
/zlogin
-S $ZONENAME \
355 /usr
/sbin
/svcadm
enable $NETPHYSDEF || \
356 error
"$e_dissvc" "$NETPHYSDEF"
359 /usr
/bin
/egrep -s "$NETPHYSNWAM" $insttmpfile
360 if (( $?
== 0 )); then
361 vlog
"$v_dissvc" "$NETPHYSNWAM"
362 /usr
/sbin
/zlogin
-S $ZONENAME \
363 /usr
/sbin
/svcadm disable
$NETPHYSNWAM || \
364 error
"$e_enblsvc" "$NETPHYSNWAM"
367 for i
in $
(/usr
/bin
/egrep network
/routing
$insttmpfile)
370 vlog
"$v_dissvc" "$i"
371 /usr
/sbin
/zlogin
-S $ZONENAME \
372 /usr
/sbin
/svcadm disable
$i || \
378 # Disable well-known services that don't run in a zone.
380 vlog
"$v_rminvalidsvcs"
381 for i
in $
(/usr
/bin
/egrep -hv "^#" \
382 /usr
/lib
/brand
/solaris10
/smf_disable.lst \
383 /etc
/brand
/solaris10
/smf_disable.conf
)
385 # Skip svcs not installed in the zone.
386 /usr
/bin
/egrep -s "$i:" $insttmpfile ||
continue
389 vlog
"$v_dissvc" "$i"
390 /usr
/sbin
/zlogin
-S $ZONENAME /usr
/sbin
/svcadm disable
$i || \
395 # Since zones can't be NFS servers, disable all of the instances of
398 for i
in $
(/usr
/bin
/egrep network
/shares
/group
$insttmpfile)
400 vlog
"$v_dissvc" "$i"
401 /usr
/sbin
/zlogin
-S $ZONENAME /usr
/sbin
/svcadm disable
$i || \
405 /usr
/bin
/rm -f $insttmpfile
411 # Remove well-known pkgs that do not work inside a zone.
415 /usr
/bin
/cat <<-EOF > $ZONEROOT/tmp/admin || fatal "$e_adminf"
429 for i
in $
(/usr
/bin
/egrep -hv "^#" /usr
/lib
/brand
/solaris10
/pkgrm.lst \
430 /etc
/brand
/solaris10
/pkgrm.conf
)
432 [[ ! -d $ZONEROOT/var
/sadm
/pkg
/$i ]] && continue
435 /usr
/sbin
/zlogin
-S $ZONENAME \
436 /usr
/sbin
/pkgrm
-na /tmp
/admin
$i >&2 || error
"$e_rmpkg" $i
441 # Zoneadmd writes a one-line index file into the zone when the zone boots,
442 # so any information about installed zones from the original system will
443 # be lost at that time. Here we'll warn the sysadmin about any pre-existing
444 # zones that they might want to clean up by hand, but we'll leave the zonepaths
445 # in place in case they're on shared storage and will be migrated to
450 zoneconfig
=$ZONEROOT/etc
/zones
452 [[ ! -d $zoneconfig ]] && return
454 if [[ -h $zoneconfig/index ||
! -f $zoneconfig/index
]]; then
455 error
"$e_badfile" "/etc/zones/index"
459 NGZ
=$
(/usr
/bin
/nawk
-F: '{
460 if (substr($1, 0, 1) == "#" || $1 == "global")
463 if ($2 == "installed")
465 }' $zoneconfig/index
)
467 # Return if there are no installed zones to warn about.
468 [[ -z "$NGZ" ]] && return
470 log
"$v_rmzones" "$NGZ"
472 NGZP
=$
(/usr
/bin
/nawk
-F: '{
473 if (substr($1, 0, 1) == "#" || $1 == "global")
476 if ($2 == "installed")
478 }' $zoneconfig/index
)
489 # ^C Should cleanup; if the zone is running, it should try to halt it.
492 trap trap_cleanup INT
495 # Parse the command line options.
501 while getopts "uvm:l:" opt
506 m
) MSG_PREFIX
="$OPTARG"; OPT_M
="-m \"$OPTARG\"";;
507 l
) LOGFILE
="$OPTARG"; OPT_L
="-l \"$OPTARG\"";;
513 (( $# < 1 )) && usage
515 (( $# > 2 )) && usage
517 [[ -n $LOGFILE ]] && exec 2>>$LOGFILE
521 # XXX shared/common script currently uses lower case zonename & zonepath
524 ZONEROOT
=$ZONEPATH/root
526 e_badinfo
=$
(gettext "Failed to get '%s' zone resource")
527 e_badfile
=$
(gettext "Invalid '%s' file within the zone")
528 v_mkdirs
=$
(gettext "Creating mount points")
529 v_nonetfix
=$
(gettext "Cannot update /etc/hostname.{net} file")
530 v_adjust
=$
(gettext "Updating the image to run within a zone")
531 v_stacktype
=$
(gettext "Stack type '%s'")
532 v_booting
=$
(gettext "Booting zone to single user mode")
533 e_bootfail
=$
(gettext "Failed to boot zone to single user mode.")
534 e_nosmf
=$
(gettext "SMF repository unavailable.")
535 v_svcsinzone
=$
(gettext "The following SMF services are installed:")
536 v_rmhollowsvcs
=$
(gettext "Deleting SMF services from hollow packages")
537 v_fixnetsvcs
=$
(gettext "Adjusting network SMF services")
538 v_rminvalidsvcs
=$
(gettext "Disabling invalid SMF services")
539 v_delsvc
=$
(gettext "Delete SMF svc '%s'")
540 e_delsvc
=$
(gettext "deleting SMF svc '%s'")
541 v_enblsvc
=$
(gettext "Enable SMF svc '%s'")
542 e_enblsvc
=$
(gettext "enabling SMF svc '%s'")
543 v_dissvc
=$
(gettext "Disable SMF svc '%s'")
544 e_dissvc
=$
(gettext "disabling SMF svc '%s'")
545 e_adminf
=$
(gettext "Unable to create admin file")
546 v_rmpkg
=$
(gettext "Remove package '%s'")
547 e_rmpkg
=$
(gettext "removing package '%s'")
548 v_rmzones
=$
(gettext "The following zones in this image will be unusable: %s")
549 v_rmzonepaths
=$
(gettext "These zonepaths could be removed from this image:")
550 v_halting
=$
(gettext "Halting zone")
551 e_shutdown
=$
(gettext "Shutting down zone %s...")
552 e_badhalt
=$
(gettext "Zone halt failed")
553 v_exitgood
=$
(gettext "Postprocessing successful.")
554 e_exitfail
=$
(gettext "Postprocessing failed.")
557 # Do some validation on the paths we'll be accessing
562 safe_dir
/var
/sadm
/install
563 safe_dir
/var
/sadm
/pkg
564 safe_opt_dir
/etc
/dfs
566 safe_opt_dir
/etc
/zones
570 # Now do the work to update the zone.
572 # Check for zones inside of image.
579 # Any errors in these functions are not considered fatal. The zone can be
580 # be fixed up manually afterwards and it may need some additional manual
581 # cleanup in any case.
584 STACK_TYPE
=$
(/usr
/sbin
/zoneadm
-z $ZONENAME list
-p | \
585 /usr
/bin
/nawk
-F: '{print $7}')
586 if (( $?
!= 0 )); then
587 error
"$e_badinfo" "stacktype"
589 vlog
"$v_stacktype" "$STACK_TYPE"
599 # Boot the zone so that we can do all of the SMF updates needed on the zone's
605 /usr
/sbin
/zoneadm
-z $ZONENAME boot
-f -- -m milestone
=none
606 if (( $?
!= 0 )); then
608 /usr
/bin
/rm -f $SMFTMPFILE
613 # Remove all files and directories installed by hollow packages. Such files
614 # and directories shouldn't exist inside zones.
616 hollow_pkgs
=$
(mktemp
-t .hollow.pkgs.XXXXXX
)
617 hollow_file_list
=$
(mktemp
$ZONEROOT/.hollow.pkgs.files.XXXXXX
)
618 hollow_dir_list
=$
(mktemp
$ZONEROOT/.hollow.pkgs.
dirs.XXXXXX
)
619 [ -f "$hollow_pkgs" -a -f "$hollow_file_list" -a -f "$hollow_dir_list" ] ||
{
621 rm -f $hollow_pkgs $hollow_file_list $hollow_dir_list
624 for pkg_name
in $ZONEROOT/var
/sadm
/pkg
/*; do
625 grep 'SUNW_PKG_HOLLOW=true' $pkg_name/pkginfo
>/dev
/null
2>&1 && \
626 basename $pkg_name >>$hollow_pkgs
628 /usr
/bin
/nawk
-v hollowpkgs
=$hollow_pkgs -v filelist
=$hollow_file_list \
629 -v dirlist
=$hollow_dir_list '
631 while (getline p <hollowpkgs > 0)
636 # fld is the field where the pkg names begin.
637 # nm is the file/dir entry name.
641 } else if ($2 == "d") {
644 } else if ($2 == "s" || $2 == "l") {
652 # Determine whether the file or directory is delivered by any
653 # non-hollow packages. Files and directories can be
654 # delivered by multiple pkgs. The file or directory should only
655 # be removed if it is only delivered by hollow packages.
656 for (i = fld; i <= NF; i++) {
657 if (pkgs[get_pkg_name($i)] != 1) {
658 # We encountered a non-hollow package. Skip
664 # The file or directory is only delivered by hollow packages.
665 # Mark it for removal.
672 # Get the clean pkg name from the fld entry.
673 function get_pkg_name(fld) {
674 # Remove any pkg control prefix (e.g. *, !)
675 first = substr(fld, 1, 1)
676 if (match(first, /[A-Za-z]/)) {
679 pname = substr(fld, 2)
682 # Then remove any class action script name
683 pos = index(pname, ":")
685 pname = substr(pname, 1, pos - 1)
688 ' $ZONEROOT/var
/sadm
/install
/contents
689 /usr
/sbin
/zlogin
-S $ZONENAME "cat /$(basename $hollow_file_list) | xargs rm -f"
690 /usr
/sbin
/zlogin
-S $ZONENAME "sort -r /$(basename $hollow_dir_list) | \
691 xargs rmdir >/dev/null 2>&1"
692 rm -f $hollow_pkgs $hollow_file_list $hollow_dir_list
694 # cleanup SMF services
697 # remove invalid pkgs
698 [[ -z $failed ]] && rm_pkgs
700 if [[ -z $failed && -n $OPT_U ]]; then
704 if (( $?
!= 0 )); then
710 /usr
/sbin
/zoneadm
-z $ZONENAME halt
711 if (( $?
!= 0 )); then
717 if [[ -n $failed ]]; then