1 #!/sbin/sh
   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 #
  23 # Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
  24 # Copyright 2014 Nexenta Systems, Inc. All rights reserved.
  25 
  26 . /lib/svc/share/smf_include.sh
  27 
  28 #
  29 # Return a list of running, non-global zones for which a shutdown via
  30 # "/sbin/init 0" may work (typically only Solaris zones.)
  31 #
  32 shutdown_zones()
  33 {
  34         zoneadm list -p | nawk -F: '{
  35                 if ($2 != "global") {
  36                         print $2
  37                 }
  38         }'
  39 }
  40 
  41 [ ! -x /usr/sbin/zoneadm ] && exit 0    # SUNWzoneu not installed
  42 
  43 if [ -z "$SMF_FMRI" ]; then
  44         echo "this script can only be invoked by smf(5)"        
  45         exit $SMF_EXIT_ERR_NOSMF
  46 fi
  47 
  48 # Make sure working directory is / to prevent unmounting problems.
  49 cd /
  50 PATH=/usr/sbin:/usr/bin; export PATH
  51 
  52 case "$1" in
  53 'start')
  54         egrep -vs '^#|^global:' /etc/zones/index || exit 0  # no local zones
  55 
  56         #
  57         # Boot the installed zones for which the "autoboot" zone property is
  58         # set and invoke the sysboot hook for all other installed zones.
  59         #
  60         ZONES=""
  61         for zone in `zoneadm list -pi | nawk -F: '{
  62                         if ($3 == "installed") {
  63                                 print $2
  64                         }
  65                 }'`; do
  66                 zonecfg -z $zone info autoboot | grep "true" >/dev/null 2>&1
  67                 if [ $? -eq 0 ]; then
  68                         [ -z "$ZONES" ] && echo "Booting zones:\c"
  69                         ZONES=yes
  70                         echo " $zone\c"
  71                         #
  72                         # zoneadmd puts itself into its own contract so
  73                         # this service will lose sight of it.  We don't
  74                         # support restart so it is OK for zoneadmd to
  75                         # to be in an orphaned contract.
  76                         #
  77                         zoneadm -z $zone boot &
  78                 else
  79                         zoneadm -z $zone sysboot &
  80                 fi
  81         done
  82 
  83         #
  84         # Wait for all zoneadm processes to finish before allowing the
  85         # start method to exit.
  86         #
  87         wait
  88         [ -n "$ZONES" ] && echo .
  89         ;;
  90 
  91 'stop')
  92         egrep -vs '^#|^global:' /etc/zones/index || exit 0  # no local zones
  93         [ "`zoneadm list`" = "global" ] && exit 0   # no zones running
  94 
  95         SVC_TIMEOUT=`svcprop -p stop/timeout_seconds $SMF_FMRI`
  96 
  97         #
  98         # First, try shutting down any running zones for which an "init 0" may
  99         # work.
 100         #
 101         MAXSHUT=`expr 3 \* $SVC_TIMEOUT \/ 4` # 3/4 of time to zone shutdown
 102         MAXHALT=`expr $SVC_TIMEOUT \/ 4`      # rest of time goes to halt
 103 
 104         zonelist=`shutdown_zones`
 105 
 106         if [ -n "$zonelist" ]; then
 107                 SHUTDOWN=0
 108                 echo "Shutting down running zones (for up to $MAXSHUT" \
 109                     "seconds):\c"
 110 
 111                 for zone in $zonelist; do
 112                         echo " $zone\c"
 113                         zoneadm -z $zone shutdown &
 114                         SHUTDOWN=1
 115                 done
 116 
 117                 [ $SHUTDOWN -eq 1 ] && echo "."
 118 
 119                 # Allow time for zones to shutdown cleanly
 120 
 121                 while [ $MAXSHUT -gt 0 -a "`shutdown_zones`" != "" ]; do
 122                         MAXSHUT=`expr $MAXSHUT - 1`
 123                         sleep 1 # wait a bit longer
 124                 done
 125         fi
 126 
 127         #
 128         # Second, try halting any non-global zones still running
 129         #
 130         WAITPIDS=""
 131         for zone in `zoneadm list`; do
 132                 if [ "$zone" != "global" ]; then
 133                         [ -z "$WAITPIDS" ] &&
 134                             echo "Zones failed to shutdown; trying to halt " \
 135                             "(for up to $MAXHALT seconds):\c"
 136                         echo " $zone\c"
 137                         zoneadm -z $zone halt &
 138                         WAITPIDS="$WAITPIDS $!"
 139                 fi
 140         done
 141         [ ! -z "$WAITPIDS" ] && echo .
 142 
 143         # Wait for the 'zoneadm halt' commands to complete.  We will let this
 144         # run forever, since the restart daemon will eventually kill us off
 145         # anyway if the halts do not complete after a certain period of time.
 146         wait $WAITPIDS
 147 
 148         # If the halts complete but a zone is still not shutdown, it might
 149         # be in a state like 'shutting_down' or 'down'.  So we give it some
 150         # time to come all the way down.
 151 
 152         while [ $MAXHALT -gt 0 -a "`zoneadm list`" != "global" ]; do
 153                 MAXHALT=`expr $MAXHALT - 1`
 154                 sleep 1 # wait a bit longer
 155         done
 156 
 157         # If there are any remaining file systems in zones, try to unmount them.
 158         umountall -Z
 159 
 160         #
 161         # Report on zones which failed to shutdown.
 162         #
 163         for zone in `zoneadm list`; do
 164                 if [ "$zone" != "global" ]; then
 165                         echo "Zone '$zone' failed to halt."
 166                 fi
 167         done
 168         [ "`zoneadm list`" != "global" ] && exit 1   # zones still running
 169         ;;
 170 
 171 *)
 172         echo "Usage: $0 { start | stop }"
 173         exit 1
 174         ;;
 175 esac
 176 exit 0