root/manageBE/create-zfsboot-gpt_livecd.sh @ 108

Revision 108, 10.6 KB (checked in by cryx, 7 months ago)

Wrong position.

RevLine 
[36]1#!/bin/sh
[37]2# Philipp Wuensche
3# This script is considered beer ware (http://en.wikipedia.org/wiki/Beerware)
4#
5# DISCLAIMER: Use at your own risk! Always make backups, don't blame me if this renders your system unusable or you lose any data!
[39]6#
[71]7# This only works with FreeBSD 8.0 (tested with 8.0-RELEASE), you have been warned!
[37]8#
9# Startup the FreeBSD livefs CD. Go into the Fixit console. Create /var/db if you want to use DHCP. Configure
[103]10# your network settings. Fetch http://anonsvn.h3q.com/s/gpt-zfsroot.sh
[37]11# Execute the script with the following parameter:
12#
[72]13# -p sets the geom provider to use, you can use multiple. Add a name for the GPT labels: -p ad4=black -p ad6=white
[59]14# -s sets the swap_partition_size to create, you can use m/M for megabyte or g/G for gigabyte
15# -S sets the zfs_partition_size to create, you can use m/M for megabyte or g/G for gigabyte, default is all available size
[37]16# -n sets the name of the zpool to create
[41]17# -f sets the ftp-server used for getting the freebsd packages, default is ftp.freebsd.org
[47]18# -m sets the zpool raid-mode, stripe (only single disk), mirror (at least two disks) and raidz (at least three disks)
19# -d sets local directory to get distribution packages from
[37]20#
21# You can use more than one device, creating a mirror. To specify more than one device, use multiple -p options.
22# eg. create-zfsboot-gpt_livecd.sh -p ad0 -p ad1 -s 512m -n tank
[36]23
[41]24ftphost='ftp.freebsd.org'
[36]25
[59]26usage="Usage: create-zfsboot-gpt_livecd.sh -p <geom_provider> -s <swap_partition_size> -S <zfs_partition_size> -n <zpoolname> -m <zpool-raidmode> -d <distdir> -f <ftphost>"
[41]27
[37]28exerr () { echo -e "$*" >&2 ; exit 1; }
29
[59]30while getopts p:s:S:n:f:m:d: arg
[37]31do case ${arg} in
32  p) provider="$provider ${OPTARG}";;
[59]33  s) swap_partition_size=${OPTARG};;
34  S) zfs_partition_size=${OPTARG};;
[47]35  n) poolname=${OPTARG};;
[41]36  f) ftphost=${OPTARG};;
[47]37  m) mode=${OPTARG};;
38  d) distdir=${OPTARG};;
[37]39  ?) exerr ${usage};;
40esac; done; shift $(( ${OPTIND} - 1 ))
41
[47]42if [ -z "$poolname" ] || [ -z "$provider" ] ; then
[37]43  exerr ${usage}
44  exit
[36]45fi
46
[71]47if [ "$distdir" -a ! -f "$distdir/base/install.sh" -o ! -f "$distdir/kernels/install.sh" -o ! -f "$distdir/src/install.sh" ]; then
[69]48  echo "Sorry, no distribution files found in ${distdir}!"
49  exit
50fi
51
[47]52# count the number of providers
53devcount=`echo ${provider} |wc -w`
54
55# set our default zpool mirror-mode
56if [ -z "$mode" ]; then
57    if [ "$devcount" -gt "1" ]; then
58        mode='mirror'
59    else
60        mode='stripe'
61    fi
62fi
63
64# check the settings for the users that want to set the mode on their own
65if [ "$devcount" -eq "1" -a "$mode" = "mirror" ]; then
66    echo "A mirror needs at least two disks!"
67    exit
68fi
69if [ "$devcount" -lt "3" -a "$mode" = "raidz" ]; then
70    echo "Sorry, you need at least three disks for a zfs raidz!"
71    exit
72fi
73
[59]74check_size () {
75  ref_disk_size=`gpart list $ref_disk | grep 'Mediasize' | awk '{print $2}'`
[73]76  if [ "${zfs_partition_size}" ]; then
[59]77    _zfs_partition_size=`echo "${zfs_partition_size}"|tr GMKBWX gmkbwx|sed -Ees:g:km:g -es:m:kk:g -es:k:"*2b":g -es:b:"*128w":g -es:w:"*4 ":g -e"s:(^|[^0-9])0x:\1\0X:g" -ey:x:"*":|bc |sed "s:\.[0-9]*$::g"`
78  fi
[73]79  if [ "${swap_partition_size}" ]; then
80    _swap_partition_size=`echo "${swap_partition_size}"|tr GMKBWX gmkbwx|sed -Ees:g:km:g -es:m:kk:g -es:k:"*2b":g -es:b:"*128w":g -es:w:"*4 ":g -e"s:(^|[^0-9])0x:\1\0X:g" -ey:x:"*":|bc |sed "s:\.[0-9]*$::g"`
81  fi
82  total_size=$((${_zfs_partition_size}+${_swap_partition_size}+162))
[59]83  if [ "${total_size}" -gt "${ref_disk_size}" ]; then
[73]84    echo "ERROR: The current settings for the partitions sizes will not fit onto your disk."
[59]85    exit
86  else
87  fi
88}
89
[71]90get_disk_labelname () {
91  label=${disk##*=}
92  disk=${disk%%=*}
93}
[59]94
[45]95echo "Creating GPT label on disks:"
[37]96for disk in $provider; do
[71]97  get_disk_labelname
[45]98  if [ ! -e "/dev/$disk" ]; then
99    echo " -> ERROR: $disk does not exist"
100    exit
101  fi
102  echo " -> $disk"
103  dd if=/dev/zero of=/dev/$disk bs=512 count=79 > /dev/null 2>&1
104  gpart create -s gpt $disk > /dev/null
[36]105done
106
[45]107echo
108sleep 1
109
[37]110smallest_disk_size='0'
[45]111echo "Checking disks for size:"
[37]112for disk in $provider; do
[71]113  get_disk_labelname
114  disk_size=`gpart show $disk | grep '\- free \-' | awk '{print $2}'`
115  echo " -> $disk - total size $disk_size"
116  if [ "$smallest_disk_size" -gt "$disk_size" ] || [ "$smallest_disk_size" -eq "0" ]; then
117    smallest_disk_size=$disk_size
118    ref_disk=$disk
119  fi
[37]120done
121
[59]122# check if the size fits
123check_size
124
[45]125echo
126echo "NOTICE: Using $ref_disk (smallest or only disk) as reference disk for calculation offsets"
127echo
128sleep 2
[37]129
[45]130echo "Creating GPT boot partition on disks:"
[37]131for disk in $provider; do
[71]132  get_disk_labelname
[45]133  echo " ->  ${disk}"
[46]134  gpart add -s 128 -t freebsd-boot $disk > /dev/null
[36]135done
136
[45]137echo
138sleep 2
[37]139
[59]140if [ "$swap_partition_size" ]; then
141  echo "Creating GPT swap partition on with size ${swap_partition_size} on disks: "
[37]142  for disk in $provider; do
[71]143    get_disk_labelname
144    echo " ->  ${disk} (Label: ${label})"
145    gpart add -s $swap_partition_size -t freebsd-swap -l swap-${label} ${disk} > /dev/null
[37]146  done
[36]147fi
148
[45]149echo
150sleep 2
[36]151
[37]152offset=`gpart show $ref_disk | grep '\- free \-' | awk '{print $1}'`
[59]153if [ -z "${zfs_partition_size}" ]; then
154  size=`gpart show $ref_disk | grep '\- free \-' | awk '{print $2}'`
155else
156  size=${zfs_partition_size}
157fi
[45]158
159echo "Creating GPT ZFS partition on with size ${size} on disks: "
[37]160for disk in $provider; do
[71]161  get_disk_labelname
162  echo " ->  ${disk} (Label: ${label})"
163  gpart add -b $offset -s $size -t freebsd-zfs -l system-${label} ${disk} > /dev/null
164  labellist="${labellist} gpt/system-${label}"
[37]165done
166
[45]167echo
168sleep 2
[37]169
[36]170# Make first partition active so the BIOS boots from it
[37]171for disk in $provider; do
[71]172  get_disk_labelname
[45]173  echo 'a 1' | fdisk -f - $disk > /dev/null 2>&1
[36]174done
175
[45]176echo
177sleep 2
[37]178
[36]179kldload /mnt2/boot/kernel/opensolaris.ko
180kldload /mnt2/boot/kernel/zfs.ko
181
182# we need to create /boot/zfs so zpool.cache can be written.
183mkdir /boot/zfs
184
185# Create the pool and the rootfs
[47]186
187if [ "$mode" = "raidz" ]; then
188  zpool create -f $poolname raidz ${labellist}
[36]189fi
[47]190if [ "$mode" = "mirror" ]; then
191  zpool create -f $poolname mirror ${labellist}
192fi
193if [ "$mode" = "stripe" ]; then
194  zpool create -f $poolname ${labellist}
195fi
[37]196
[47]197if [ `zpool list -H -o name $poolname` != "$poolname" ]; then
198  echo "ERROR: Could not create zpool $poolname"
[45]199  exit
200fi
[37]201
[45]202sleep 2
203
[103]204echo "Setting checksum to fletcher4"
205zfs set checksum=fletcher4 ${poolname}
[36]206
[106]207rootzfs="$poolname/ROOT/$poolname"
208
[59]209zfs create -p $rootzfs
[54]210zfs set freebsd:boot-environment=1 $rootzfs
[47]211
[36]212# Now we create some stuff we also would like to have in seperate filesystems
[105]213for filesystem in usr-src usr-obj usr-local tmp; do
[47]214   echo "Creating $poolname/$filesystem"
215   zfs create $poolname/$filesystem
[42]216   if [ "$filesystem" = "tmp" ]; then
[47]217     chmod 1777 /$poolname/tmp
[42]218   fi
[47]219   zfs umount $poolname/$filesystem
[36]220   _filesystem=`echo $filesystem | sed s:-:\/:g`
[47]221   zfs set mountpoint=/${_filesystem} $poolname/${filesystem}
[36]222done
223
[47]224mkdir /$rootzfs/usr
[36]225
[47]226zfs set mountpoint=/$rootzfs/usr/src $poolname/usr-src
227zfs mount $poolname/usr-src
[36]228
[47]229zfs set mountpoint=/$rootzfs/usr/obj $poolname/usr-obj
230zfs mount $poolname/usr-obj
[36]231
232echo ####################################
[47]233if [ -z "$distdir" ]; then
234    echo "Now installing base, ssys, slib and kernels via $ftphost. This may take a while, depending on your network connection."
235    zfs create $poolname/installdata
236    cd /$poolname/installdata
237   
238    if [ `pwd` != "/$poolname/installdata" ]; then
239        echo "ERROR: Could not change directoy to /$poolname/installdata. Aborting."
240        exit
241    fi
242   
243    sleep 2
244    arch=`uname -p`
245    release=`uname -r`
246    echo
247    echo "Fetching FreeBSD ${release}-${arch}:"
248    for pkg in base kernels; do
249        mkdir /$poolname/installdata/${pkg}
250        cd /$poolname/installdata/${pkg}
251        echo " -> $pkg"
252        ftp -V "$ftphost:pub/FreeBSD/releases/${arch}/${release}/${pkg}/*"
253    done
254    mkdir /$poolname/installdata/src
255    cd /$poolname/installdata/src/
256    echo " -> ssys"
257    ftp -V "$ftphost:pub/FreeBSD/releases/${arch}/${release}/src/ssys*"
258    echo " -> slib"
259    ftp -V "$ftphost:pub/FreeBSD/releases/${arch}/${release}/src/slib*"
260    ftp -V "$ftphost:pub/FreeBSD/releases/${arch}/${release}/src/install.sh"
261    distdir="/$poolname/installdata"
262else
263    echo "Using distribution packages from $distdir"
[45]264fi
265
[47]266export DESTDIR=/$rootzfs/
[36]267
[45]268echo
269echo "Extracting base into $DESTDIR"
[47]270cd /$distdir/base ; cat base.?? | tar --unlink -xpzf - -C ${DESTDIR:-/}
271cd /$distdir/src ;     sh ./install.sh sys lib
[45]272echo "Extracting kernel into ${DESTDIR}boot"
[47]273cd /$distdir/kernels ; sh ./install.sh generic
[36]274
[47]275cd /$rootzfs/boot ; cp -rp GENERIC/* /$rootzfs/boot/kernel/
[36]276
[47]277if [ -z "$distdir" ]; then
278    zfs destroy $poolname/installdata
279fi
[36]280
[47]281echo 'LOADER_ZFS_SUPPORT=YES' >> /$rootzfs/etc/make.conf
282
[45]283echo
284echo "I will now build the ZFS aware boot-loader, expect some funky compile output and ignore the errors."
285sleep 2
[36]286echo '#!/bin/sh
287mount -t devfs devfs /dev
288export DESTDIR=""
289cd /usr/src/sys/boot/
[45]290make -s obj
291make -s depend
292make -s
293mkdir -p /usr/share/man/man5
294cd /usr/src/sys/boot/i386/loader; make -s install
295cd /usr/src/sys/boot/i386/zfsboot; make -s install
296cd /usr/src/sys/boot/i386/gptzfsboot; make -s install
297cd /usr/src/sys/boot/i386/pmbr; make -s install
[36]298umount /dev
[47]299exit' > /$rootzfs/tmp/chroot-command.sh
300chmod +x /$rootzfs/tmp/chroot-command.sh
301chroot /$rootzfs/ /tmp/chroot-command.sh
302rm /$rootzfs/tmp/chroot-command.sh
[36]303
[108]304# fix usr/share/man/man8
305rm /$rootzfs/usr/share/man/man8
306
[45]307echo
308echo "Installing new bootcode on disks: "
[37]309for disk in $provider; do
[71]310  get_disk_labelname
[45]311  echo " ->  ${disk}"
[47]312  gpart bootcode -b /$rootzfs/boot/pmbr -p /$rootzfs/boot/gptzfsboot -i 1 $disk > /dev/null
[36]313done
[45]314echo
[36]315
316# We need to fix /usr/src so it is mounted correct when booting from ZFS
[47]317zfs umount $poolname/usr-src
318zfs set mountpoint=/usr/src $poolname/usr-src
[36]319
320# We need to fix /usr/obj so it is mounted correct when booting from ZFS
[47]321zfs umount $poolname/usr-obj
322zfs set mountpoint=/usr/obj $poolname/usr-obj
[36]323
324# Enable the new filesystem as zpool bootfs
[103]325zpool set bootfs=$rootzfs $poolname
[36]326
327# We still need to tell the kernel from where to mount its root-filesystem
[47]328echo 'zfs_load="YES"' >> /$rootzfs/boot/loader.conf
329echo "vfs.root.mountfrom=\"zfs:$rootzfs\"" >> /$rootzfs/boot/loader.conf
330echo 'zfs_enable="YES"' >> /$rootzfs/etc/rc.conf
331touch /$rootzfs/etc/fstab
[36]332
[59]333if [ "$swap_partition_size" ]; then
[45]334  echo "Adding swap partitions in fstab:"
[38]335  for disk in $provider; do
[71]336    get_disk_labelname
337    echo " ->  /dev/gpt/swap-${label}"
338    echo "/dev/gpt/swap-${label} none swap sw 0 0" >> /$rootzfs/etc/fstab
[38]339  done
[36]340fi
[45]341echo
[36]342
343# Copy the zpool.cache to the new filesystem
[47]344cp /boot/zfs/zpool.cache /$rootzfs/boot/zfs/zpool.cache
[36]345
346sleep 5
347
[59]348echo "Please reboot the system from the harddisk(s), remove the FreeBSD CD from you cdrom!"
Note: See TracBrowser for help on using the browser.