Commit ede28955 authored by Ryan Jackson's avatar Ryan Jackson

Added scripts to support a Linux MFS. Also began modifications to rc.frisbee...

Added scripts to support a Linux MFS.  Also began modifications to rc.frisbee and slicefix to make them less FreeBSD-specific.
parent 9d803873
......@@ -41,10 +41,53 @@ DEFRUNLVLDIR ?= $(RCDIR)/rc3.d
# without DESTDIR, used for the value of symlinks
RRCDIR ?= /etc/rc.d
destdircheck:
@if [ -z "$(DESTDIR)" ]; then \
echo "You must define DESTDIR for this target!"; \
false; \
fi
@if [ "$(DESTDIR)" = "/" ]; then \
echo "DESTDIR is '/', really really bad idea!"; \
false; \
fi
install client-install: common-install etc-install \
sup-install script-install bin-install vserver-install
@echo "Remember to install the PEM files if necessary"
mfs-install: destdircheck common-install etc-install \
script-install bin-install
rm -f $(BINDIR)/rc/rc.mkelab
rm -f $(RCDIR)/elvind.sh
@if [ ! -f $(ISMFS) ]; then \
echo >$(ISMFS) "This file indicates its the MFS. DO NOT DELETE!"; \
fi
frisbee-mfs-install: destdircheck
$(INSTALL) -m 644 $(SRCDIR)/frisbee/rc.local $(SYSETCDIR)/rc.local
$(INSTALL) -m 755 $(SRCDIR)/dhclient-exit-hooks \
$(SYSETCDIR)/dhclient-exit-hooks
$(INSTALL) -m 755 $(SRCDIR)/dhclient-enter-hooks \
$(SYSETCDIR)/dhclient-enter-hooks
@if [ -r $(SRCDIR)/master.passwd ]; then \
$(INSTALL) -m 600 $(SRCDIR)/master.passwd $(SYSETCDIR); \
pwd_mkdb -d $(SYSETCDIR) $(SYSETCDIR)/master.passwd; \
if [ ! -e $(DESTDIR)/bin/csh ]; then \
ln $(DESTDIR)/bin/sh $(DESTDIR)/bin/csh; \
fi \
fi
@if [ -r $(SRCDIR)/group ]; then \
$(INSTALL) -m 644 $(SRCDIR)/group $(SYSETCDIR); \
fi
$(INSTALL) -m 755 $(SRCDIR)/control_interface $(SYSETCDIR)/testbed
$(INSTALL) -m 755 $(SRCDIR)/rc.frisbee $(SYSETCDIR)/testbed
$(INSTALL) -m 755 $(SRCDIR)/rc.ipod $(SYSETCDIR)/testbed
$(INSTALL) -m 755 $(SRCDIR)/slicefix $(SYSETCDIR)/testbed
$(INSTALL) -m 755 -s ../tmcc-nossl $(SYSETCDIR)/testbed/tmcc
$(INSTALL) -m 755 -s ../findif $(SYSETCDIR)/testbed
rm -f $(BINDIR)/rc/rc.mkelab
rm -f $(RCDIR)/elvind.sh
simple-install: common-install script-install bin-install
dir-install:
......@@ -138,6 +181,7 @@ script-install: dir-install $(SCRIPTS)
$(INSTALL) -m 755 $(SRCDIR)/nodetype $(BINDIR)/nodetype
$(INSTALL) -m 755 $(SRCDIR)/chipset.awk $(BINDIR)/chipset.awk
$(INSTALL) -m 755 $(SRCDIR)/cpuspeed.awk $(BINDIR)/cpuspeed.awk
$(INSTALL) -m 755 $(SRCDIR)/rc.mfs $(BINDIR)/rc/rc.mfs
sfs-install:
$(INSTALL) -m 755 -o root -g root -d $(DESTDIR)/etc/sfs
......
#! /bin/sh
disk=$1
part=$2
if [ $# -ne 2 ]; then
exit 1
fi
freebsd_slices=`fdisk -l /dev/$disk 2> /dev/null | \
sed -n '/a5 *FreeBSD/s#^/dev/'$disk'\([0-9]*\) .*$#\1#p'`
total_slices=`fdisk -l /dev/$disk | grep "^/dev/$disk[0-9]" | wc -l`
if [ $total_slices -eq 0 ]; then
exit 1;
fi
if [ -z "$freebsd_slices" ]; then
# No slices?
exit 1
fi
dmesg_output=`dmesg | grep " *$disk$part: <bsd: $disk[0-9]* "`
# Valid disklabels should be properly parsed by linux. If it didn't like
# the label, we can't mount anything.
if [ -z "$dmesg_output" ]; then
# invalid disklabel
exit 1
fi
(
# Change partition types to empty for all other FreeBSD slices
# so we can get the disklabel for the correct slice. These
# changes don't get written to disk. They're just here because
# Linux's fdisk sucks and doesn't let us specify which partition's
# disklabel to edit.
for slice in $freebsd_slices; do
[ $slice -eq $part ] && continue
echo t # Change slice type
if [ $total_slices -gt 1 ]; then
echo $slice # Specify slice
fi
echo 0 # Set to empty type
done
echo b # Change to BSD disklabel mode
echo p # Print disklabel
echo q # Quit (don't write to disk)
) | fdisk /dev/$disk 2> /dev/null | grep '^ *a:' > /dev/null
rc=$?
# Valid disklabel, but no 'a' partition.
if [ $rc -ne 0 ]; then
exit 1
fi
# We have a valid disklabel with an 'a' partition.
# Output the Linux device name for it.
echo $dmesg_output | cut -d' ' -f3
exit 0
#! /bin/sh
disk=$1
part=$2
if [ -z "$disk" ] || [ -z "$part" ]; then
echo "Usage: ${0##*/} disk partition"
exit 1
fi
# figure out the linux device name
dunit=`echo $disk | sed -e 's/..\([0-7]\)/\1/'`
case $disk in
# IDE
ad[0-3])
dtype="hd"
d=`echo $dunit | sed -e 'y/0123/048c/'`
lrootdev="3${d}${part}"
;;
# SATA
ad[4-7])
dtype="sd"
dunit=`expr $dunit - 4`
lrootdev="8${dunit}${part}"
;;
# SCSI
da[0-7])
dtype="sd"
lrootdev="8${dunit}${part}"
;;
# Megaraid
amrd[0-7])
dunit=`echo $disk | sed -e 's/amrd\([0-7]\)/\1/'`
dtype="sd"
lrootdev="8${dunit}${part}"
;;
*)
echo "${0##*/}: linux: unknown disk $disk" 1>&2
return 1
;;
esac
dunit=`echo $dunit | sed -e 'y/01234567/abcdefgh/'`;
ldisk=$dtype$dunit
echo $ldisk $lrootdev
#!/bin/sh
#
# EMULAB-COPYRIGHT
# Copyright (c) 2000-2007 University of Utah and the Flux Group.
# All rights reserved.
#
# Optional flag argument says "do not reboot"
#
reboot=1
if [ $# -eq 1 -a "$1" = "-noreboot" ]; then
reboot=0
fi
OS=`uname -s`
#
# Amount of memory in MB to leave for everyone else in the system. If you
# get out-of-memory or vm_pager error while running frisbee, increase this.
#
RESIDMEM=32
if [ -r /etc/emulab/paths.sh ]; then
. /etc/emulab/paths.sh
else
BINDIR=/etc/testbed
BOOTDIR=/etc/testbed
ETCDIR=/etc/testbed
fi
# Behave a little different on widearea nodes.
isrem=0
if [ -e $ETCDIR/isrem ]; then
isrem=1
fi
get_value()
{
local data="$1"
local key="$2"
echo $data | tr ' ' '\n' | sed -n "s/^$key=//p"
}
#
# Update the MBR of the given disk to the indicated "version."
#
# XXX this is somewhat of a hack right now. We recognize two
# versions of the MBR:
# v1 (partition 1 size 6281352)
# v2 (partition 1 size 12305790)
# Currently we only install a new MBR if the existing one is the
# wrong size, just in case the user has customized the boot program.
#
install_mbr()
{
local disk=$1
local new_mbr_ver=$2
local cur_mbr_ver=''
if ! dd if=$disk of=/dev/null bs=512 count=1 2>/dev/null; then
echo "WARNING: could not read from $disk, MBR not changed"
return -1
fi
if [ "$OS" = Linux ]; then
size=`echo -e 'u\np\nq' | fdisk $disk | \
sed -n "s#^${disk}1 *. *[0-9]* *\([0-9]*\).*\\$#\1#p"`
elif [ "$OS" = FreeBSD ]; then
size=`fdisk -s ${disk##*/} 2>/dev/null | \
sed -n -e 's/^ *1: *[0-9][0-9]* *\([0-9][0-9]*\).*$/\1/p'`
fi
case ${size}s in
6281352s)
cur_mbr_ver=1
;;
12305790s)
cur_mbr_ver=2
;;
s)
echo "Found no MBR on $disk, installing version $new_mbr_ver"
;;
*)
echo "WARNING: custom MBR on $disk, not changed"
return 0
;;
esac
if [ "$cur_mbr_ver" = $new_mbr_ver ]; then
return 0
fi
if ! [ -r $MBR_PATH/mbr{$new_mbr_ver}.dd ]; then
echo "WARNING: cannot find MBR version $new_mbr_ver, not installed"
return -1
fi
echo "Installing MBR version $new_mbr_ver ..."
dd if=$MBR_PATH/mbr{$new_mbr_ver}.dd of=$disk bs=512 count=1
# Linux won't re-read the partition table unless told to do so.
# hdparm could be used for this, but it may not be installed.
# fdisk tells the kernel to re-read the table after writing it
# to disk, so we'll just use that.
if [ $OS = Linux ]; then
echo "Re-reading partition table ..."
echo w | fdisk $disk > /dev/null
fi
}
#
# Function to zero all potential superblocks in the DOS partitions that
# could interfere with the OSes on the image being loaded.
#
# FreeBSD 4 or 5 goes out of its way to make this hard. In FBSD4, we
# cannot overwrite the beginning of partitions that have a legit superblock.
# In FBSD5, DOS partitions that have a zero type cannot even be accessed.
# So we have to use the whole-disk special file using offsets extracted
# via fdisk. This is unnecessary with Linux, but it's easier just to do it
# the same way on both OSs rather than have special-case code.
#
zap_superblocks()
{
local disk=$1
local offsets=''
if [ $OS = Linux ]; then
offsets=`echo -e 'u\np\nq' | fdisk $disk | \
sed -n "s#^${disk}[0-9]* *. *[0-9]* *\([0-9]*\).*\\$#\1#p"`
elif [ $OS = FreeBSD ]; then
offsets=`fdisk -s ${disk##*/} 2>/dev/null | \
sed -n -e 's/^[ 0-9]*: *\([0-9]*\).*$/\1/p'`
fi
if [ x"$offs" = x ]; then
return 0
fi
echo -n "Invalidating old potential superblocks: "
for off in $offsets; do
echo -n "$off "
dd if=/dev/zero of=$disk seek=$off bs=512 count=16 > /dev/null 2>&1
if [ $? -ne 0 ]; then
echo "WARNING: failed to invalidate $off"
fi
done
echo ""
return 0
}
get_buffer_sizes()
{
local memargs
local hostmem
local bytes
local datasegsz
# set memory limits:
# allow $RESIDMEM MB for non-frisbee stuff
# split remaining memory (min of 2MB) between network/disk buffering
#
if [ $OS = FreeBSD ]; then
hostmem=`sysctl -n hw.usermem`
hostmem=`expr $hostmem / 1048576`
if [ $hostmem -ge `expr $RESIDMEM + 2` ]; then
hostmem=`expr $hostmem - $RESIDMEM`
bytes=`expr $hostmem \* 1024`
datasegsz=`ulimit -d`
if [ $bytes -gt $datasegsz ]; then
bytes=$datasegsz
hostmem=`expr $bytes / 1024`
echo "WARNING: kernel limits buffering to $hostmem MB"
fi
ulimit -v $bytes
## For GaTech we use more memory for disks since the disks are so slow
#netmem=`expr $hostmem \* 1 / 3`
#diskmem=`expr $hostmem \* 2 / 3`
#memargs="-C $netmem -W $diskmem"
# For Utah, we let the client split up the memory
# (50/50, but no more chunk buffers than there are chunks in the image)
memargs="-M $hostmem"
fi
fi
echo $memargs
}
# FIXME shouldn't hard code "/images"
write_image()
{
local address=$1
local disk=$2
local slice=$3
local port=""
local imagefile=""
local protocol=${address%%://*}
if [ $protocol = $address ]; then
case $address in
/*) protocol=file ;;
*) protocol=frisbee ;;
esac
fi
case $protocol in
frisbee)
port=${address##*:}
if [ $port = $address ]; then
echo "*** WARNING: no port specified for frisbee"
return -1
fi
address=${address%%:*}
;;
http|https)
server=${address%%/*}
filename=${address#*/}
if ! [ -d /images ]; then
echo "Need to create or mount /images directory!"
return 1
fi
if ! $BINDIR/mkextrafs.pl -f $disk /images; then
echo "Could not create /images partition"
return 1
fi
wget -nv -N -P /images \
$protocol://$server/$filename
rc=$?
if [ $rc -eq 0 ]; then
echo "wget succeeded getting the image"
else
echo "wget failed, status $rc"
return -1
fi
imagefile=/images/${filename##*/}
;;
file)
imagefile=/$address
;;
*)
echo "*** WARNING: Unsupported protocol $protocol!"
return -1
;;
esac
$BINDIR/tmcc state RELOADING
if [ $protocol = frisbee ]; then
$BINDIR/frisbee -m $address -p $port -s $slice $FRISBEE_OPTS $disk
rc=$?
if [ $rc -ne 0 ]; then
echo "Frisbee run failed, status $rc"
return $rc
fi
echo "Frisbee run finished"
rc=0
else
$BINDIR/imageunzip $IMAGEUNZIP_OPTS -s $slice $imagefile $disk
rc=$?
fi
if mount | grep /images > /dev/null; then
umount /images
fi
return $rc
}
$BINDIR/tmcc state RELOADSETUP
time=30
while [ $time -gt 0 ]; do
sleep 1
LOADINFO=`$BINDIR/tmcc loadinfo`
[ -n "$LOADINFO" ] && break
time=$(( $time - 1 ))
done
if [ $time -eq 0 ]; then
echo "*** Failed to get loadinfo data" 1>&2
exit 2
fi
BOSSINFO=`$BINDIR/tmcc bossinfo`
BOSSIP=${BOSSINFO##* }
# For testing purposes.
#BOSSINFO='boss.emulab.net 155.101.128.70'
#LOADINFO='ADDR=234.5.6.69:4444'
ADDRESS=`get_value "$LOADINFO" ADDR`
PARTOS=`get_value "$LOADINFO" PARTOS`
PARTITION=`get_value "$LOADINFO" PART`
PARTITION=${PARTITION:-'0'}
DISK=`get_value "$LOADINFO" DISK`
DISK=${DISK:-'ad0'}
ZFILL=`get_value "$LOADINFO" ZFILL`
ZFILL=${ZFILL:-'0'}
ACPI=`get_value "$LOADINFO" ACPI`
ASF=`get_value "$LOADINFO" ASF`
MBR=`get_value "$LOADINFO" MBRVERS`
# Convert from the FreeBSD device names to Linux device names
# if necessary.
if [ $OS = "Linux" ]; then
case $DISK in
[hs]d[a-z])
;;
*)
OLD_DISK=$DISK
DISK=`$BINDIR/freebsd_to_linux_disk $DISK 0`
DISK=${DISK%% *}
;;
esac
fi
FRISBEE_OPTS="-S $BOSSIP"
if [ -z "$ADDRESS" ]; then
echo "Unable to get address for loading image"
exit 1
fi
# FIXME shouldn't hardcode path
if [ -x /usr/sbin/ntpdate ]; then
/usr/sbin/ntpdate -b $BOSSIP >/dev/null 2>&1
fi
if [ $PARTITION -ne 0 ]; then
FRISBEE_OPTS="$FRISBEE_OPTS -s $PARTITION"
case $PARTOS in
FreeBSD) PTYPE=165 ;;
OpenBSD) PTYPE=166 ;;
Fedora|Linux) PTYPE=131 ;;
esac
[ -n "$PTYPE" ] && FRISBEE_OPTS="$FRISBEE_OPTS -D $PTYPE"
fi
# Enable IPoD
if [ -r $BINDIR/rc.ipod ]; then
. $BINDIR/rc.ipod
fi
FRISBEE_OPTS="$FRISBEE_OPTS `get_buffer_sizes`"
if [ -e $BOOTDIR/myip ]; then
FRISBEE_OPTS="$FRISBEE_OPTS -i `cat $BOOTDIR/myip`"
fi
IMAGEUNZIP_OPTS="-o -O -W 32"
# ZFILL==1: use frisbee
# ZFILL==2: separate disk-wipe pass (not yet implemented)
if [ "$ZFILL" != "0" ]; then
FRISBEE_OPTS="$FRISBEE_OPTS -z"
IMAGEUNZIP_OPTS="$IMAGEUNZIP_OPTS -z"
fi
device=/dev/$DISK
if [ $PARTITION -ne 0 ]; then
if [ $OS = Linux ]; then
device=$device$PARTITION
elif [ $OS = FreeBSD ]; then
device=${device}s$PARTITION
fi
fi
is_remote=0
[ -e $ETCDIR/isrem ] && is_remote=1
if [ $OS = FreeBSD ]; then
# Make sure the necessary device files exist (only necessary on FreeBSD 4.x)
# Note that we create partition files for all slices, not just slice 1,
# for the benefit of the slicefix script.
#
if [ -x /dev/MAKEDEV -a ! -e /dev/$DISK ]; then
(cd /dev; ./MAKEDEV $DISK ${DISK}s2a ${DISK}s3a ${DISK}s4a)
fi
fi
# For slice images, ensure that the MBR is the correct version
# and replace if not.
if [ "$PARTITION" != "0" ]; then
install_mbr /dev/$DISK $MBR
fi
# If not zeroing the disk and we are loading a full disk image
# we need to ensure that we at least invalidate any old superblocks
# that might leak through (most likely in partition 4 which isn't
# touched by our current image). We do this before running frisbee
# so that any legit filesystems loaded from the image work.
# Since we do it before frisbee, we are counting on the current
# MBR being the same as the MBR being layed down. While not
# a reasonable assumption in general, it mostly works in our
# environment and at least won't hurt anything if not true.
if [ $is_remote -eq 0 -a $PARTITION -eq 0 -a $ZFILL -eq 0 ]; then
zap_superblocks /dev/$DISK
fi
install_mbr /dev/$DISK $MBR
echo "Resizing final disk partition"
growdisk -vW /dev/$DISK
if [ $OS = FreeBSD ]; then
# Make sure the write-cache is enabled on SCSI disks. It makes a
# huge difference. We don't worry about data corruption in the
# case of a crash, because we will just reload the disk again anyway
# in that situation.
#
turncacheoff=0
case $DISK in
da*)
if [ -x $BINDIR/camwce ] && $BINDIR/camwce on $DISK; then
turncacheoff=1;
fi
;;
esac
fi
write_image $ADDRESS /dev/$DISK $PARTITION
rc=$?
if [ $rc -ne 0 ]; then
echo "Failed to write image to disk, status $rc"
exit 1
fi
if [ $OS = FreeBSD ]; then
# Turn the cache back off if we turned it on.
# Is this sufficient to ensure the cache gets flushed?
#
if [ $turncacheoff -eq 1 ]; then
$BINDIR/camwce off $DISK
fi
fi
echo "Adjusting slice-related files"
export SLICEFIX_ACPI=$ACPI
export SLICEFIX_ASF=$ASF
$BINDIR/slicefix $PARTITION $DISK
echo "Image load complete at `date`"
#
# If requested to reboot, do so.
#
# Note: there is a race condition with stated here.
# If we reboot immediately after sending RELOADDONE,
# it is possible that, under heavy server load, we will
# finish the reboot and reach the bootinfo stage before
# stated gets and processes our RELOADDONE. So now we
# wait around after sending the RELOADDONE. stated should
# force us to reboot when the transition takes place.
# For backward compatibility we use a new state: RELOADDONEV2.
# For paranoia we just wait around for awhile and then
# reboot anyway, just in case stated's reboot fails for
# some reason.
#
if [ $reboot -eq 1 ]; then
$BINDIR/tmcc state RELOADDONEV2
echo "Waiting for server to reboot us ..."
if [ $isrem -eq 1 ]; then
sleep 30
else
sleep 240
fi
echo "No response from server, rebooting myself ..."
/sbin/reboot
sleep 100
else
$BINDIR/tmcc state RELOADDONE
fi
#echo "Failed to load disk, dropping to login prompt at `date`"
#exit 1
#!/usr/bin/perl -w
#
# EMULAB-COPYRIGHT
# Copyright (c) 2004, 2005 University of Utah and the Flux Group.
# All rights reserved.
#
use English;
use Getopt::Std;
#
# This script is run directly from boot. It should NOT be run after