A Script to Install Diskless Clients

From: Ian G Batten (igb@fulcrum.bt.co.uk)
Date: Tue Jul 14 1992 - 04:51:05 CDT


just in case this is useful to anyone, this is how i install diskless
workstations. i used to use the sun add_client script and then tweak it
with a perl script, but this does the whole job. i started down this
route because i use disk mirroring quite a lot which breaks the sun
mechanism for determining the amount of space available, and i use amd
quite a bit.

this is chock-full of local assumptions, but it shows you the steps you
need to follow.

i use /export/root/group{1,2} for the roots, /export/swap/moby{1,2,3,4}
for swap partitions and use one 8M lump in each per workstation. the
rest is fairly obvious.

i'm posting it because it took me a while to figure out all the things
that needed doing to get a workstation on the air. it assumes that
ethers and hosts are correct and then does the rest...

just move your eyes swiftly over the part that shows i'm using the sun4m
bootstrap for a sun4c...works for me!

ian

#!/usr/local/bin/perl

# this script installs a workstation onto our main server,
# whose nc400 card is called ``doctor-seuss-nfs''. it shows
# at least the set of tasks that need to be carried out to
# install a diskless client.

# i don't use the sun admin scripts because they make too many
# assumptions which break under our disk mirroring regime.
# and most of this script is fixing things up afterwards: the
# task carried out by add_client is trivial.

# i.g.batten@fulcrum.bt.co.uk

# get the messages out correctly

select STDOUT;
$| = 1;

# return the canonical name, the ip number and the bootstrap name
# (hardwired assumption: it's a SUN4C).

sub hostinfo {
    local ($in_name) = @_;
    local ($name, $aliases, $addrtype, $length, @addrs) =
        gethostbyname ($in_name);
    die "can't resolve $in_name" unless $name;
    local ($b1, $b2, $b3, $b4) = unpack ('C4', $addrs[0]);
    local ($addr) = sprintf ("%d.%d.%d.%d", $b1, $b2, $b3, $b4);
    local ($bootname) =
        sprintf ("%02X%02X%02X%02X.SUN4C", $b1, $b2, $b3, $b4);
    ($name, $addr, $bootname);
}

# simple wrapper around `cp'.

sub copy_file {
    local ($src, $dst) = @_;
    ($dst = '.') unless $dst;
    print "copying $src to $dst ...";
    system ("/bin/cp $src $dst") && die "bad copy";
    print "OK\n";
}

# very simple question asker

sub ask
{
    local ($prompt) = @_;

    print $prompt;
    $response = <STDIN>;
    chop $response;
    $response;
}

# spacefor --- are there space kbytes free in place for fs?

sub spacefor
{
    local ($kbytes, $system) = @_;
    ($system = '.') unless $system;

    open (DF, "/bin/df $system|") || die "can't start df for space";
    $discard = <DF>; # discard the header
    ($dev, $size, $used, $avail, $capacity, $mount) = split (/[\t\n ]+/, <DF>);
    close DF;

    die "not enough space --- need $kbytes kbytes in $mount"
        unless $avail > $kbytes;
}

# you must be root to do this sort of thing

die "you lose! you must be root!" unless $> == 0;

# either take things on the command line or ask for them

$host = $ARGV[0];
$rootbase = $ARGV[1];

($host = &ask ("Hostname: ")) unless $host;
($rootbase = &ask ("Base root: ")) unless $rootbase;

# hard-wire them in one place rather than everywhere...

$server = 'doctor-seuss-nfs';
$proto = '/export/exec/proto.root.sunos.4.1.2';
$bootstrap = '/tftpboot/boot.sun4m.sunos.4.1.2';
$kernel = 'vmunix.DISKLESS_ELC';
$kvm = '/export/exec/kvm/sun4c.sunos.4.1.2';

# find the machine we're after

($canon, $addr, $bootname) = &hostinfo ($host);

$short = $canon;
$short =~ s/\..*//;

print "full name is $canon; short name is $short\n";

# and get information about (presumably) ourselves

($ser_canon, $ser_addr) = &hostinfo ($server);

# ensure we know where we're going to put ourselves

chdir $rootbase || die "no directory $rootbase";

# check we have space to do this

&spacefor (3 * 1024);

mkdir ($short, 0755) || die "can't make root directory";
chdir $short || die "failed somehow to make viable root";

$root = `pwd`;
chop $root;

print "transferring basic root...";
system ("(cd $proto; /bin/tar cf - .) | /bin/tar xf -") &&
    die "couldn't transfer basic root";
print "OK...";

chdir "sbin" || die "no sbin in proto root";

print "and sbin...";
system ("(cd /sbin; /bin/tar cf - .) | /bin/tar xf -") &&
    die "couldn't transfer sbin";
print "OK\n";

chdir $root;

print "making usr...";
mkdir ('usr', 0755) || die "can't make usr";
print "OK\n";

print "making bootstrap...";
symlink ($bootstrap, "/tftpboot/$bootname") ||
    die "couldn't make bootstrap";
print "OK\n";

# sort out bootparams
print "updating server bootparams...";
open (BP, ">>/etc/bootparams") || die "can't open bootparams";
print BP "$canon \\\n";
print BP " swap=$server:/export/swap/moby1/$short\\\n";
print BP " root=$server:$root\n";
close BP;
print "OK\n";

print "rhosts...";
open (RHOSTS, ">.rhosts") || die "can't make rhosts";
print RHOSTS "kether.fulcrum.co.uk\n";
close RHOSTS;
print "OK\n";

# there's a stripped kernel in / on the server (we hope).

&copy_file ("/$kernel");
link ($kernel, 'vmunix') || die "can't link kernel";

# there's a horrible mistake in the proto root

chmod (0777, 'var/tmp') || die "can't open /var/tmp to world";

print "devices (this will take a while)...";
chdir "dev" || die "no dev for $canon";
print "standard...";
system ('./MAKEDEV std') && die "no MAKEDEV available";
print "and pty...";
system ('./MAKEDEV pty') && die "no MAKEDEV available";
print "OK\n";
chdir "..";

# now fiddle the config tables
chdir 'etc' || die "no etc for $canon";

print "now working in etc...\n";

# route via the server
print "defaultrouter...";
open (DR, ">defaultrouter") || die "can't open defaultrouter";
print DR "$ser_canon\n";
close DR;
print "OK\n";

# all sendmail machines have the same config file
&copy_file ("/etc/sendmail.cf");

# now we need some sort of hosts file, just to boot off
print "hosts...";
open (HOSTS, ">hosts") || die "can't open hosts";
print HOSTS "# This is only consulted during booting.\n";
print HOSTS "# It was generated from the extra script by igb.\n";
print HOSTS "# The yellow pages maps were inspected to find the truth.\n\n";

print HOSTS "127.0.0.1 localhost\n";
print HOSTS "$ser_addr $ser_canon\n";
print HOSTS "$addr $canon\n";

close HOSTS;
print "OK\n";

# now fstab needs to be set up
print "fstab...";
open (FSTAB, ">fstab") || die "can't open fstab";
print FSTAB "$ser_canon:$root / nfs rw 0 0\n";
print FSTAB "$ser_canon:/usr /usr nfs ro 0 0\n";
print FSTAB "$ser_canon:$kvm /usr/kvm nfs ro 0 0\n";
print FSTAB "$ser_canon:/usr/share /usr/share nfs rw 0 0\n";
print FSTAB "swap /tmp tmp rw 0 0\n";
close FSTAB;
print "OK\n";

# we used to do an exportfs -a, but that takes an eternity if it;s
# a large file (and it will be!).

# we set $| on EXPORTS because we are printing and then instantly using
# the results.

print "exports and swapfiles...";
open (EXPORTS, ">>/etc/exports") || die "can't open /etc/exports";
select EXPORTS;
$| = 1;
select STDOUT;
print EXPORTS "$root -access=$short,root=$short\n";
system ("/usr/etc/exportfs $root") && die "can't export $root";

# make the swapfiles

for $moby ("moby1", "moby2", "moby3", "moby4")
{
    print "$moby...";
    &spacefor (8 * 1024, "/export/swap/$moby");
    system ("/usr/etc/mkfile 8m /export/swap/$moby/$short")
        && die "can't make";
    print EXPORTS "/export/swap/$moby/$short -access=$short,root=$short\n";
    system ("/usr/etc/exportfs /export/swap/$moby/$short")
        && die "can't export";
}

close EXPORTS;

print "OK\n";

# copy the standard files:

&copy_file ('/etc/ttytab.client', 'ttytab');
&copy_file ('/etc/inetd.conf');
&copy_file ('/etc/syslog.conf');
&copy_file ('/etc/rc.local');
&copy_file ('/etc/hosts.allow');
&copy_file ('/etc/hosts.deny');
&copy_file ('/etc/defaultdomain');

print "ntp.conf...";
open (NTPCONF, ">ntp.conf") || die "can't make ntp.conf";
print NTPCONF "broadcastclient yes\n";
print NTPCONF "driftfile /etc/ntp.drift\n";
close NTPCONF;
print "OK\n";

# manufacture the little places for xdm

chdir "../var/spool" || die "can't find spool area";

print "var/spool/X11/xdm...";
mkdir ('X11', 0755) || die "can't make X11";
mkdir ('X11/xdm', 0755) || die "can't make X11/xdm";

print "OK\n";



This archive was generated by hypermail 2.1.2 : Fri Sep 28 2001 - 23:06:44 CDT