Monday, October 22, 2007

my book world dropping off the network

A bit ago I posted about getting a Western Digital My Book World WDG2NC10000 1TB box. I had it drop off the network a couple times and stopped trying to move data over to it en mass until I could resolve the problems. After digging through one of those crappy knowledge bases (when will people learn what a wiki is?) I found this: "If there is heavy I/O load put on the network and WD My Book World Edition hard drive, it is recommended that a static IP address be used rather than DHCP." with no explanation.

I switched to a static IP and I'v moved 50gb or so now without it dropping off the network onces, whereas before it'd drop somewhere around 10gb or so. Working much better now.

Friday, October 12, 2007

Putting Oracle Database in a deb package for ubuntu

While at Haydrian we began toying a bit with Oracle database. Using Ubuntu a debian package was needed but Oracle has it's own out of control installer that's gui based. I'm not an Oracle DBA, so this was a learning experience. I couldn't find deb's out there, so I wrote a build system to make one in a cheating way. This is in no form ready for public use, but it's a great place to start if you want to put Oracle in a deb.

Grab the tar file here Basically you need to take a build box that's clean and run the build.sh there. You'll need to either have the oracle archive ready locally or on a server, see build.sh before you run it. It'll check for dependencies and try to make an install, then package it up. It won't pass a lintian check or anything at all. it doesn't meet any LSB shit. It's a mess. but it was working for us best as anyone could tell me.

the build shell runs a few python scripts that poke around that box and try to ensure it meets the requirements that oracle presents in the lengthy install document. It builds some trees, then runs the oracle installer headless in a preseed/unattended mode. Note that the install is big, a couple of gigs. You'll need more than that because of the hacked up way I stuff it into a deb.

A former coworker said there is something better out there than when I last looked. Maybe he'll comment and add it. Anyways, ask me any questions. I got permission to GPL all of this, so feel free to do something decent with it. There'll be proprietary configurations in there (like the non-FSB directory trees). I figure at this point it's best it's just out there, as I don't have the time or the desire to work with it.

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:


# 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...