1 #!/usr/bin/bash
   2 
   3 #
   4 # This file and its contents are supplied under the terms of the
   5 # Common Development and Distribution License ("CDDL"), version 1.0.
   6 # You may only use this file in accordance with the terms of version
   7 # 1.0 of the CDDL.
   8 #
   9 # A full copy of the text of the CDDL should have accompanied this
  10 # source.  A copy of the CDDL is also available via the Internet at
  11 # http://www.illumos.org/license/CDDL.
  12 #
  13 
  14 #
  15 # Copyright 2017 OmniTI Computer Consulting, Inc.  All rights reserved.
  16 #
  17 
  18 ListDisks() {
  19   declare -A disksize
  20   declare -A diskname
  21   for rdsk in $(prtconf -v | grep dev_link | awk -F= '/\/dev\/rdsk\/c.*p0/{print $2;}')
  22   do
  23     disk=`echo $rdsk | sed -e 's/.*\///g; s/p0//;'`
  24     size=`prtvtoc $rdsk 2>/dev/null | awk '/bytes\/sector/{bps=$2} /sectors\/cylinder/{bpc=bps*$2} /accessible sectors/{print ($2*bps)/1048576;} /accessible cylinders/{print int(($2*bpc)/1048576);}'`
  25     disksize+=([$disk]=$size)
  26   done
  27 
  28   disk=""
  29   while builtin read diskline
  30   do
  31     if [[ -n "$disk" ]]; then
  32       desc=`echo $diskline | sed -e 's/^[^\<]*//; s/[\<\>]//g;'`
  33       diskname+=([$disk]=$desc)
  34       disk=""
  35     else
  36       disk=$diskline
  37     fi
  38   done < <(format < /dev/null | awk '/^ *[0-9]*\. /{print $2; print;}')
  39 
  40   for want in $*
  41   do
  42     for disk in "${!disksize[@]}" ; do
  43       case "$want" in
  44         \>*)
  45             if [[ -n ${disksize[$disk]} && "${disksize[$disk]}" -ge "${want:1}" ]]; then
  46               echo $disk
  47             fi
  48           ;;
  49         \<*)
  50             if [[ -n ${disksize[$disk]} && "${disksize[$disk]}" -le "${want:1}" ]]; then
  51               echo $disk
  52             fi
  53           ;;
  54         *)
  55           if [[ "$disk" == "$want" ]]; then
  56             echo $disk
  57           fi
  58           ;;
  59       esac
  60     done
  61 
  62     for disk in "${!diskname[@]}" ; do
  63       case "$want" in
  64         ~*)
  65           PAT=${want:1}
  66           if [[ -n $(echo ${diskname[$disk]} | egrep -e "$PAT") ]]; then
  67             echo $disk
  68           fi
  69           ;;
  70       esac
  71     done
  72   done
  73 }
  74 ListDisksAnd() {
  75   EXPECT=$(( $(echo "$1" | sed -e 's/[^,]//g;' | wc -c) + 0))
  76   for part in $(echo "$1" | sed -e 's/,/ /g;'); do
  77     ListDisks $part
  78   done | sort | uniq -c | awk '{if($1=='$EXPECT'){print $2;}}'
  79 }
  80 ListDisksUnique(){
  81   for term in $*; do
  82     ListDisksAnd $term
  83   done | sort | uniq | xargs
  84 }
  85 
  86 BuildRpoolOnly() {
  87   ztype=""
  88   ztgt=""
  89   disks=`ListDisksUnique $*`
  90   log "Disks being used for root pool $RPOOL: $disks"
  91   if [[ -z "$disks" ]]; then
  92     bomb "No matching disks found to build root pool $RPOOL"
  93   fi
  94   rm -f /tmp/kayak-disk-list
  95   for i in $disks
  96   do
  97     if [[ -n "$ztgt" ]]; then
  98       ztype="mirror"
  99     fi
 100     ztgt="$ztgt ${i}"
 101     # Keep track of disks for later...
 102     echo ${i} >> /tmp/kayak-disk-list
 103   done
 104   log "zpool destroy $RPOOL (just in case we've been run twice)"
 105   zpool destroy $RPOOL 2> /dev/null
 106   log "Creating root pool with: zpool create -f $RPOOL $ztype $ztgt"
 107   # Just let "zpool create" do its thing. We want GPT disks now.
 108   zpool create -f $RPOOL $ztype $ztgt || bomb "Failed to create root pool $RPOOL"
 109 }
 110 BuildRpool() {
 111   BuildRpoolOnly $*
 112   BuildBE
 113 }
 114 GetTargetVolSize() {
 115     # Aim for 25% of physical memory (minimum 1G)
 116     # prtconf always reports in megabytes
 117     local mem=`/usr/sbin/prtconf | /bin/awk '/^Memory size/ { print $3 }'`
 118     if [[ $mem -lt 4096 ]]; then
 119         local vsize=1
 120     else
 121         local quart=`echo "scale=1;$mem/4096" | /bin/bc`
 122         local vsize=`printf %0.f $quart`
 123     fi
 124     echo $vsize
 125 }    
 126 GetRpoolFree() {
 127     local zfsavail=`/sbin/zfs list -H -o avail $RPOOL` 
 128     if [[ ${zfsavail:(-1)} = "G" ]]; then
 129         local avail=`printf %0.f ${zfsavail::-1}`
 130     elif [[ ${zfsavail:(-1)} = "T" ]]; then
 131         local gigs=`echo "scale=1;${zfsavail::-1}*1024" | /bin/bc`
 132         avail=`printf %0.f $gigs`
 133     else
 134         # If we get here, there's too little space left to be usable
 135         avail=0
 136     fi
 137     echo $avail
 138 }
 139 MakeSwapDump() {
 140     local size=`GetTargetVolSize`
 141     local totalvols=""
 142     local usable=""
 143     local finalsize=""
 144     local savecore=""
 145 
 146     # We're creating both swap and dump volumes of the same size
 147     let totalvols=${size}*2
 148 
 149     # We want at least 10GB left free after swap/dump
 150     # If we can't make swap/dump at least 1G each, don't bother
 151     let usable=`GetRpoolFree`-10
 152     if [[ $usable -lt 2 ]]; then
 153         log "Not enough free space for reasonably-sized swap and dump; not creating either."
 154         return 0
 155     fi
 156 
 157     # If the total of swap and dump is greater than the usable free space,
 158     # make swap and dump each take half but don't enable savecore
 159     if [[ $totalvols -ge $usable ]]; then
 160         let finalsize=${usable}/2
 161         savecore="-n"
 162     else
 163         finalsize=$size
 164         savecore="-y"
 165     fi
 166 
 167     for volname in swap dump; do
 168         /sbin/zfs create -V ${finalsize}G $RPOOL/$volname || \
 169             bomb "Failed to create $RPOOL/$volname"
 170     done
 171     printf "/dev/zvol/dsk/$RPOOL/swap\t-\t-\tswap\t-\tno\t-\n" >> $ALTROOT/etc/vfstab
 172     Postboot /usr/sbin/dumpadm $savecore -d /dev/zvol/dsk/$RPOOL/dump
 173     return 0
 174 }