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 }