ubuntu lvm network install part 2
A while back I wrote a bit about working on getting a complex lvm configuration built out of a network install of ubuntu (debian too, remember the installers are pretty similar). A couple people have messaged me or commented on the thread with some questions. As of recently I'm not working at Haydrian anymore, in search of a better engineering role, but I did talk to a couple of the executives there about extracting some of those configuration files for everyones benefit.
As I mentioned earlier partman[-auto] doesn't really support multiple disk or partition lvm configuration. So the trick is basically replacing partman with shell scripts. First bit in making everything automatic is configuring the preseed file:
Now note that this is basically a direct copy of the running code at work, with some proprietary bits pulled out. You'll definately need to update "yourserver.local" There's some bits in there where we used a local repository. I highly recommend doing this, use apt-mirror or something. It speeds things up quite a bit. I needed to get a copy of a security update repository going but never got a chance to.
It's worth noting if I haven't already that how i download and place the script is important. Certain stages of the install download and unpackage udebs which would overwrite modifications put directly in the initrd. don't change this plan unless you research the installer design.
Now for lvm.sh which is the replacement script for partman. Note that there is a lot of specific bullshit in this script. I almost pulled it out but decided it might be useful as another example.
You may notice from the case statement that there's more than one phase here. Remember when i mentioned the installer overwriting files? you can't just overwrite partman from "early_command in the preseed" because when that is run the partman udeb's have not been unpacked yet.
To fully automate the install you've got to get through all the language shit. Currently when doing a network install this is asked first during the installation process, which is before the preseed file is downloaded (and of course you have to tell the installer to use the preseed file, duh). So any locale shit needs to be on the command line rather than in the preseed file. This should be similiar to your pxelinux configuration:
Your paths and server names will all need to be updated as one would expect. I believe that's all you need. Feel free to post comments which is better than emailing me questions because i can answer it publicly without reposting the question, and i do get an email notification on comments anyways and check them out pretty quickly. I haven't touched this stuff in two months or so, so I easily could have left something out. Some day I'll remember to talk about buggy PXE implementations on hardware that doesn't like fragmented packets...
As I mentioned earlier partman[-auto] doesn't really support multiple disk or partition lvm configuration. So the trick is basically replacing partman with shell scripts. First bit in making everything automatic is configuring the preseed file:
# keymap/language/local/network done on kernel bootline since it's before we fetch this preseed file
d-i debconf/priority string critical
d-i time/zone string US/Pacific
d-i clock-setup/utc boolean true
# Avoid that last message about the install being complete.
d-i finish-install/reboot_in_progress note
# network settings
d-i preseed/early_command string wget http://yourserver.local/ubuntu/config/lvm.sh -P /tmp ; chmod 755 /tmp/lvm.sh ; echo /tmp/lvm.sh installer >> /var/lib/dpkg/info/download-installer.postinst
# Install source
d-i mirror/country string enter information manually
d-i mirror/http/hostname string yourserver.local
d-i mirror/http/directory string /ubuntu
d-i mirror/suite string feisty
d-i mirror/http/proxy string
d-i apt-setup/universe boolean true
d-i apt-setup/multiverse boolean true
d-i apt-setup/restricted boolean true
d-i apt-setup/local0/repository string http://yourserver.local/ubuntu repo feisty #feisty-security
d-i apt-setup/local0/comment string local repository
# this should choose the most minimal install known so far
tasksel tasksel/first standard
# probably not needed
d-i pkgsel/install-pattern string ~t^ubuntu-standard$
# prevents (possible) usplash installation
d-i base-installer/kernel/linux/extra-packages-2.6 string
# install additional apps
d-i pkgsel/include string openssh-server
# prevents language-pack-en which installs firefox/openoffice language support which installs X11
d-i pkgsel/language-pack-patterns string
d-i pkgsel/install-language-support string false
# cut installation down to the bone (doesn't appear to work) FIXME
base-install base_install/base_exclude alsa-base,alsa-utils,wireless-tools,wpasupplicant,popularity-contest,ppp,pppconfig,pppoeconf,tcpdump,telnet,w3m
# preconfigure packages
ssh ssh/run_sshd boolean true
d-i grub-installer/only_debian boolean true
d-i partman-auto/disk string /dev/hda
d-i partman-auto/method string regular
d-i partman-auto/choose_recipe select boot-root
d-i partman/confirm boolean true
d-i partman/choose_partition select Finish partitioning and write changes to disk
Now note that this is basically a direct copy of the running code at work, with some proprietary bits pulled out. You'll definately need to update "yourserver.local" There's some bits in there where we used a local repository. I highly recommend doing this, use apt-mirror or something. It speeds things up quite a bit. I needed to get a copy of a security update repository going but never got a chance to.
It's worth noting if I haven't already that how i download and place the script is important. Certain stages of the install download and unpackage udebs which would overwrite modifications put directly in the initrd. don't change this plan unless you research the installer design.
Now for lvm.sh which is the replacement script for partman. Note that there is a lot of specific bullshit in this script. I almost pulled it out but decided it might be useful as another example.
#!/bin/sh
# Copyright 2007 Haydrian Corporation
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see http://www.gnu.org/licenses/.
#
# Manually create LVM configuration
# Partman does not currently support multi-disk lvm
# Designed to be run after download-installer but before partman-base
# This allows us to modify partman-base.postinst after it's been dropped in by anna
# Partman appears to be entirely an external program, removing the call to partman from partman-base.postinst prevents it from running.
# note about the capabilities of the debian-installer image: there's no python, perl, awk or bc.
# bases around busybox which provides among others: [, cut, egrep, logger -s -t, printf, sed, sort, tr, uniq, wget
case "$1" in
installer)
# we should have d-i downloaded by now.
# partman comes in a udeb from the network so we have to hook here
# and replace the partman-base.postinst file
sed -i 's/partman/\/tmp\/lvm.sh partman/' /var/lib/dpkg/info/partman-base.postinst
logger -s -t lvm.sh modified partman-base.postinst
;;
partman)
# do filesystem stuff: detect our config, fdisk, lvms, mount /target
logger -s -t lvm.sh partition configuration starting
modprobe dm_mod
# FIXME: This is going to be really dirty to handle our configurations. More work will need to be done later.
# dev3 xm3 1200: sda: 1171842048 hda: 125056
# vian xm3 1200: sda: 976519168 hda: 58605120
# xm3-lite 1100: sda: 732389376 hda:
# dev4 xm3 2200: sda: 244198584 hda: sdb: 1562456064
# Above what disk size should we use LVM instead of a big root (for test boxes?, vmware) value in kbytes (100,000,000 = 100GB)
LVM_THRESHOLD=100000000
# strip the header from partitions and grab device names from fourth column if the major number is 8 (scsi/sata) or 3 (ide)
# exit with SIZE_diskdev variables with each diskdev (sda, sdb) in bytes)
# grab the alphanumeric text from the last column from line 3 to the end of file
# note that [:alnum:] will exclude devmapper devices due to the 'dm-n' format.
for part in `sed -n -e "3,/^END/s/.* \([[:alnum:]]*\)$/\1/p" < /proc/partitions` ; do
upart=`echo $part | tr a-z A-Z`
export "SIZE_$upart"=`sed -n "s/.* \([0-9]*\) $part$/\1/p" < /proc/partitions`
done
echo sda: $SIZE_SDA hda: $SIZE_HDA sdb: $SIZE_SDB
# check for separate physical boot drive
# sfdisk: -uB blocks, -uM megabytes. /proc/partition gives blocks
# parttypes: 83 linux, 82 swap, 8e lvm
if [ $SIZE_HDA ] && [ $SIZE_SDA -gt $LVM_THRESHOLD ]; then
logger -s -t lvm.sh chosing XM3 1100/1200 Style partitioning
# we have the boot disk create a primary partition
# This is an XM3 1100 or 1200 with the 128MB boot disk
echo ",,83" | sfdisk /dev/hda
# pvcreate filters (ignored by filtering) if the there's a partition table
dd if=/dev/zero of=/dev/sda bs=512 count=1
pvcreate -ff -y /dev/sda
BOOT=/dev/hda1
LVM=/dev/sda
elif [ $SIZE_SDA ] && [ $SIZE_SDB -gt $LVM_THRESHOLD ]; then
logger -s -t lvm.sh chosing XM3 2200 Style partitioning
# big disk is SDB and we have a smaller SDA, Model 2200
# SDA is for boot
echo ",,83" | sfdisk /dev/sda
logger -s -t lvm.sh DEBUG "`ls -l /dev/sdb`"
# pvcreate filters (ignored by filtering) if the there's a partition table
dd if=/dev/zero of=/dev/sdb bs=512 count=1
logger -s -t lvm.sh DEBUG "`ls -l /dev/sdb`"
pvcreate -ff -y /dev/sdb
BOOT=/dev/sda1
LVM=/dev/sdb
elif [ $SIZE_SDA -gt $LVM_THRESHOLD ] ; then
logger -s -t lvm.sh chosing dev box style partitioning
# no separate boot drive, testing boxes with a single disk
# creates a 256mb boot partition, makes the rest an LVM
echo -e ",256,83\n,,8e" | sfdisk -uM /dev/sda
pvcreate -ff -y /dev/sda2
BOOT=/dev/sda1
LVM=/dev/sda2
else
logger -s -t lvm.sh chosing vmware/light style partitioning
# Weird stituation or VMWARE, play with caution
# make the root 90% of the disk, swap the rest
ROOTSIZE=$(( $SIZE_SDA - $SIZE_SDA / 10 ))
echo -e ",$ROOTSIZE,83\n,,82" | sfdisk -uB /dev/sda
# don't set boot, because we're not having one
# don't set LVM either and don't make one
fi
if [ $BOOT ]; then
logger -s -t lvm.sh formating boot partition: $BOOT
mke2fs -L 'BOOT' -q $BOOT
fi
if [ $LVM ]; then
logger -s -t lvm.sh lvm: building VG
# default to large extents
vgcreate -s 256M system $LVM
# Get total extents
EXTENTS=`pvdisplay | sed -n 's/Total PE *\([0-9]*\)/\1/p'`
# So bash can't do floating point math. we don't have python/perl/bc/awk
# 28% apps1, apps2, archive == 84
# 3% config1, config2 == 6 + . = 90
# 5% swap varlog == 10 + . = 100
#reducing the 28 to 27
_27PERCENT=$(( $EXTENTS * 27 / 100 ))
_03PERCENT=$(( $EXTENTS * 3 / 100 ))
_05PERCENT=$(( $EXTENTS * 5 / 100 ))
#reducing original amounts so their are free extents everywhere
logger -s -t lvm.sh lvm: building LVs
lvcreate -l $_03PERCENT -n config1 system
lvcreate -l $_03PERCENT -n config2 system
lvcreate -l $_03PERCENT -n swap system
lvcreate -l $_03PERCENT -n varlog system
lvcreate -l $_27PERCENT -n apps1 system
lvcreate -l $_27PERCENT -n apps2 system
lvcreate -l $_27PERCENT -n archives system
logger -s -t lvm.sh lvm: creating filesystems
for fs in config1 config2 varlog apps1 apps2 archives ; do mkfs.reiserfs -q /dev/system/$fs 1>/dev/null; done
logger -s -t lvm.sh lvm: creating swap
mkswap /dev/system/swap
swapon /dev/system/swap
else
# not using LVMS (vmware)
logger -s -t lvm.sh simple: creating root
mke2fs -L 'ROOT' -q /dev/sda1
logger -s -t lvm.sh simple: creating swap
mkswap /dev/sda2
swapon /dev/sda2
fi
# Create directory structure
logger -s -t lvm.sh creating mountpoints and preparing
mkdir /target
mount /dev/system/config1 /target -treiserfs
mkdir /target/boot
if [ $BOOT ] ; then
mount $BOOT /target/boot -text2
fi
if [ $LVM ] ; then
mkdir -p /target/var/log
mkdir -p /target/apps
mkdir -p /target/archives
mount /dev/system/varlog /target/var/log
fi
# Create fstab
logger -s -t lvm.sh creating fstab
mkdir /target/etc
echo \# /etc/fstab: static file system information. > /target/etc/fstab
echo \# >> /target/etc/fstab
echo "#" >> /target/etc/fstab
if [ $BOOT ] ; then
echo 'LABEL="BOOT" /boot ext2 defaults 1 2' >> /target/etc/fstab
fi
if [ $LVM ] ; then
echo /dev/system/config1 / reiserfs acl,user_xattr 1 1 >> /target/etc/fstab
echo /dev/system/apps1 /apps reiserfs acl,user_xattr 1 2 >> /target/etc/fstab
echo /dev/system/archives /archives reiserfs acl,user_xattr 1 2 >> /target/etc/fstab
echo /dev/system/varlog /var/log reiserfs acl,user_xattr 1 2 >> /target/etc/fstab
echo /dev/system/swap none swap sw 0 0 >> /target/etc/fstab
else #vmwarish
echo /dev/sda1 / ext2 defaults 1 1 >> /target/etc/fstab
echo /dev/sda2 none swap sw 0 0 >> /target/etc/fstab
fi
echo proc /proc proc defaults 0 0 >> /target/etc/fstab
# Secret udev rules hack for xm3 1200/1100 network cards
mkdir -p /target/etc/udev/rules.d
echo \# on board e100 > /target/etc/udev/rules.d/50-xm3network.rules
echo KERNELS==\"0000:00:06.0\", NAME=\"eth2\" >> /target/etc/udev/rules.d/50-xm3network.rules
echo \# on board tg3 \(2x1000\) >> /target/etc/udev/rules.d/50-xm3network.rules
echo KERNELS==\"0000:02:09.0\", NAME=\"eth0\" >> /target/etc/udev/rules.d/50-xm3network.rules
echo KERNELS==\"0000:02:09.1\", NAME=\"eth1\" >> /target/etc/udev/rules.d/50-xm3network.rules
;;
*)
echo $0: This script is destructive and should only be run as part of the debian-installer process
;;
esac
You may notice from the case statement that there's more than one phase here. Remember when i mentioned the installer overwriting files? you can't just overwrite partman from "early_command in the preseed" because when that is run the partman udeb's have not been unpacked yet.
To fully automate the install you've got to get through all the language shit. Currently when doing a network install this is asked first during the installation process, which is before the preseed file is downloaded (and of course you have to tell the installer to use the preseed file, duh). So any locale shit needs to be on the command line rather than in the preseed file. This should be similiar to your pxelinux configuration:
LABEL xm3-300
kernel ubuntu/amd64/feisty/linux
append vga=normal initrd=ubuntu/amd64/feisty/initrd.gz console-setup/ask_detect=false console-setup/layoutcode=us debian-installer/locale=en_US kbd-chooser/method=us netcfg/choose_interface=eth0 netcfg/get_hostname=xm3 preseed/locale=en_US preseed/url=http://yourserver.local/ubuntu/config/feisty-xm3.cfg
Your paths and server names will all need to be updated as one would expect. I believe that's all you need. Feel free to post comments which is better than emailing me questions because i can answer it publicly without reposting the question, and i do get an email notification on comments anyways and check them out pretty quickly. I haven't touched this stuff in two months or so, so I easily could have left something out. Some day I'll remember to talk about buggy PXE implementations on hardware that doesn't like fragmented packets...



0 Comments:
Post a Comment
<< Home